SQL Server 2008: насколько безопасным является отказоустойчивая хранимая процедура, которая загружает неуправляемые библиотеки - PullRequest
4 голосов
/ 15 апреля 2009

У нас есть обычная (т.е. не расширенная) хранимая процедура в SQL Server 2000 , которая вызывает внешний exe-файл. Этот exe-файл, в свою очередь, загружает DLL-файл, полученный из SDK, и вызывает из него некоторые процедуры (например, Init, DoStuff, Shutdown).

Единственная причина, по которой мы имеем этот внешний exe-компонент, заключается в том, что мы не хотели создавать расширенную хранимую процедуру, которая вызывала бы .dll. Мы полагали, что если dll завершится сбоем (маловероятное событие, но все же), то также произойдет сбой процесса SQL Server, а это не то, что мы хотели. При использовании внешнего exe-файла только этот exe может аварийно завершить работу.

Теперь мы обновляем SQL Server 2008 и рассматриваем возможность создания хранимой процедуры CLR, которая вызывает эту проблему и, следовательно, избавляется от exe. Этот SP, конечно, будет помечен как UNSAFE. В связи с этим вопрос заключается в том, является ли это безопасным (более безопасным, достаточно безопасным и т. Д.) Таким способом по сравнению с подходом расширенного SP?

Единственная важная вещь, которую я выследил на BOL:

Указание UNSAFE разрешает код в собрание, чтобы выполнить незаконное операции с SQL Server пространство процесса, и, следовательно, может потенциально ставит под угрозу надежность и масштабируемость SQL Server

, но я не уверен, отвечает ли он на мой вопрос, потому что я не стремлюсь к «надежности и масштабируемости», а скорее после стабильности и поддержания работоспособности.

PS: Мы хотим избавиться от exe-файла, потому что это вызывает неудобства при управлении разрешениями SP (вы знаете, тот материал, который неожиданно применяется к вам, если вы вызываете SP, который содержит xp_cmdshell).

Ответы [ 2 ]

3 голосов
/ 04 июля 2009

Поскольку этот код изначально использовался с расширенными хранимыми процедурами, похоже, что это неуправляемый код. Ошибки в неуправляемом коде могут легко привести к сбою вашего процесса.

Интеграция с CLR намного надежнее, чем расширенные хранимые процедуры, но код все еще выполняется в процессе, поэтому ошибки могут привести к сбою или повреждению SQL Server. (Для сравнения, теоретически, процедура SAFE CLR не сможет повредить SQL Server, хотя даже она может вызвать проблемы, которые снижают доступность вашего сервера без полного отключения SQL Server.)

По сути, единственные способы не завершить работу SQL Server в этом сценарии:

  1. Избегайте использования сбойных функций.
  2. Исправьте код ошибки.
  3. Запуск кода в отдельном процессе (запуск исполняемого файла, вызов службы Windows, вызов веб-службы и т. Д.). Вы можете написать управляемую .NET DLL для выполнения этого взаимодействия. Скорее всего, вам все равно придется загружать его небезопасно, но - если оно написано правильно - на самом деле это может быть вполне безопасно.
1 голос
/ 08 апреля 2016

В связи с этим вопрос заключается в том, является ли это безопасным (более безопасным, достаточно безопасным и т. Д.) Таким способом по сравнению с подходом расширенного SP?

Обычно да. Я имею в виду, если вы обрабатываете процесс ОС, то вы делаете это и процессу ОС. Я не понимаю, как использовать API расширенной хранимой процедуры, чтобы сделать это, было бы обязательно безопаснее, чем API SQLCLR, особенно когда может произойти сбой процесса ОС, который находится вне базы данных.

Конечно, я не уверен насчет XP API, так как я не использовал его, но я знаю следующее:

  • API XP устарел, и рекомендуется, чтобы все новые проекты, которые могут быть реализованы с использованием любой из этих технологий, выполнялись в SQLCLR.
  • SQLCLR допускает более детальные разрешения, чем два других, включая возможность выполнять олицетворение (если для входа в систему, выполняющего объекты SQLCLR, используется вход в систему Windows).
  • SQLCLR API разделяется по процессам / памяти как по базе данных, так и по владельцу сборки (т. Е. Пользователю, указанному в предложении AUTHORIZATION). Следовательно, у вас может быть проблема со сборкой в ​​одной БД, не затрагивая объекты SQLCLR в других БД (или даже в той же БД, если есть сборки, принадлежащие другому пользователю, хотя на практике это, вероятно, редко случается, так как большинство людей просто используйте значение по умолчанию dbo).

Я не уверен, отвечает ли он на мой вопрос, потому что я не после «надежности и масштабируемости», а скорее после стабильности и поддержания работоспособности.

Что ж, в SQLCLR, безусловно, есть что-то, что можно сделать, когда для Assembly установлено значение UNSAFE:

  • потенциально запись в реестр (в зависимости от доступа, предоставленного учетной записи «Вход в систему», выполняющей процесс SQL Server, или имени входа, выполняющего функцию SQLCLR, если олицетворение включено, и это вход в систему Windows).
  • потенциально записать в файловую систему
  • потенциально может взаимодействовать с процессами, работающими в системе
  • совместно использовать память с другими SPID-серверами SQL Server (т.е. сессиями), выполняющими функции из той же сборки (то есть этой конкретной сборки в этой БД, принадлежащей этому пользователю). Вероятно, это больше всего ускользает от людей, поскольку это неожиданно, когда вы привыкли к консольным приложениям и приложениям Windows, имеющим свои собственные отдельные области памяти, но здесь, потому что это один домен приложений на сборку на БД на владельца, все сеансы, выполняющие этот код, совместно используют все static переменные. Большая часть кода написана с предположением, что AppDomain является частным, и поэтому хранение значений в статических переменных эффективно, поскольку оно кэширует значение, но в SQLCLR вы можете получить неожиданное поведение, если два процесса перезаписывают значения друг друга и читают другие значение сеанса.
  • потенциальные утечки памяти. Атрибуты защиты хоста пытаются запретить вам использовать встроенную функциональность .NET, которая может сделать это, например, использовать TimeZoneInfo для преобразования времени между TimeZoneID, но атрибуты защиты хоста не применяются в UNSAFE сборках.
  • возможно , что поток, выполняющий метод SQLCLR, обрабатывается по-разному при выполнении кода UNSAFE / FullTrust (кооперативная многозадачность против Preemptive). Я думал, что прочитал, что потоки UNSAFE управляются по-другому, но я не уверен, где я это читаю, и ищу источник.

Но, учитывая все вышесказанное, если вы вызываете внешний EXE-файл, он имеет свой собственный домен приложений.

Итак, вы можете сделать следующее:

  1. продолжайте вызывать EXE с помощью оболочки SQLCLR для Process.Start(). Это дает вам как разделение процесса / памяти , так и возможность более легко контролировать разрешения для одной хранимой процедуры, которая будет когда-либо вызывать только этот EXE-файл, и никто не сможет его изменить (по крайней мере, без изменения этого кода SQLCLR и переустановка сборки).

  2. установить экземпляр SQL Server Express на том же компьютере, загрузить туда объекты SQLCLR и создать связанные серверы в обоих направлениях (от текущего экземпляра SQL Server до нового экземпляра SQL Server Express и от него), чтобы вы могли легко общаться между ними. Это позволит вам изолировать выполнение SQLCLR и исключить его из основного процесса SQL Server.

Конечно, что, как говорится, 1063, насколько это действительно опасно? То есть, насколько вероятно, что процесс полностью завершится сбоем и удалит все вместе с ним? Конечно, это не невозможно, но обычно сбой приводит к удалению только домена приложений, а не самого хоста CLR. Я думаю, что гораздо более вероятно, что код, который не дает сбоя, но написан плохо и потребляет слишком много памяти и / или процессора, будет проблемой, с которой сталкиваются люди.

...