Кроме перезапуска SQL Server, есть ли способ принудительно сбросить домен приложений SQLCLR?

11

Я хочу заставить AppDomain, используемый SQLCLR, быть сброшенным. Как я могу сделать это, кроме перезапуска экземпляра SQL Server?

Джастин Даринг
источник
Не уверен, что вы получаете уведомления об обновлениях ответов, но я обновил свой ответ еще более простым способом :).
Соломон Руцкий,

Ответы:

6

Я знаю, что это немного жестоко, но как насчет отключения CLR и его повторного включения?

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 0;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO
Макс Вернон
источник
2
Одна важная деталь этого метода заключается в том, что он работает при работе с базой данных STANDBY (только для чтения); все остальные методы, которые я пробовал, нет. Я нуждался в этом, потому что обновление сборки CLR распространялось как обычно через доставку журналов в каталог STANDBY, но AppDomain не перезагружался - поэтому он продолжал выполнять код из старой версии .dll в течение дня.
Грейнджер
@Granger очень интересно и полезно знать :). Тем не менее, я считаю, что это ошибка в SQL Server. Возможно, вы захотите сообщить об этом через сайт Connect: connect.microsoft.com/SQLServer/Feedback
Соломон Руцки
1
@srutzky - Спасибо за предложение; Я ожидаю, что они просто закроют отчет как «Не исправлю». Настройка для всего сервера, а не для каталога (как «вложенные триггеры», «уровень доступа к файловому потоку» и т. Д.). Эту банку с червями я бы попытался открыть.
Грейнджер
@Granger (и Макс): я не понимал, что я говорил, я думал, что это ошибка. Я не говорил, что сброс настроек «CLR Enabled», вызывающих выгрузку, был ошибкой. Я говорил, что ALTER ASSEMBLYраспространяемый через доставку журналов, который не перезагружал (или, по крайней мере, не выгружал) App Domain, был ошибкой. В любом случае, я нашел еще более простой метод, который я добавил к своему ответу здесь. Если бы у вас была возможность протестировать этот новый метод, это было бы здорово, мне было бы очень интересно посмотреть, работает ли он в описанном вами сценарии доставки журналов.
Соломон Руцкий,
8

Существует более элегантное решение, которое не повлияет на все остальные сборки: просто измените PERMISSION_SET одной из сборок в домене приложения (домены приложения для каждого пользователя).

ALTER ASSEMBLY [AssemblyName] WITH PERMISSION_SET = {1 of the 2 levels that 
                                                      this assembly is not current at}

Просто помните, что вам нужно будет установить PERMISSION_SET обратно к тому, что было. Кроме того, вам нужно получить доступ к методу в сборке, прежде чем изменение PERMISSION_SET будет выгружать его; изменение сборки, которая в данный момент не загружена в домен приложения, который активен, но с другой сборкой, не влияет на домен приложения (домены приложения для каждой БД, для пользователя, а не для каждой сборки).


ОБНОВЛЕНИЕ
Метод, описанный выше, является наиболее детальным подходом, когда он выгружает только один домен приложения. Но для этого требуется, чтобы сборка могла быть установлена ​​на один из двух других уровней. Для сборок, отмеченных как SAFEэто будет возможно, только если

  • база данных установлена ​​в TRUSTWORTHY ONили
  • сборка подписана, и Логин, основанный на асимметричном ключе, который сам основан на той же самой подписи, что и сборка, существует и получил либо разрешение, EXTERNAL ACCESS ASSEMBLYлибо UNSAFE ASSEMBLYразрешение

В этом случае вы можете просто повернуть TRUSTWORTHYнастройку, ONа затем сразу же OFFснова вернуться, и это разгрузит все домены приложений в этой конкретной базе данных:

ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;

Если у вас есть только один домен приложений в базе данных в любом случае (и я подозреваю, что это имеет место в 95% или более случаев), тогда оба описанных здесь метода имеют одинаковый чистый эффект. И в этой ситуации ALTER DATABASEметод кажется более простым, так как он не требует указания конкретного имени объекта и не требует знания оригинала PERMISSION_SET.

ТАКЖЕ, если у вас есть только один домен приложения, то этот ALTER DATABASEметод проще, даже если база данных уже установлена TRUSTWORTHY ONили вы настроили регистрацию на основе ключей с соответствующим разрешением. Если вы используете логин на основе ключей , то вы можете установить , TRUSTWORTHYчтобы ONзатем OFFснова , как уже упоминалось выше. Но если вы уже TRUSTWORTHYустановили на ON, то просто измените его и установите на, OFFа затем немедленно вернитесь к ON:

ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
Соломон Руцкий
источник
1
Обновленный подход работает с каталогом базы данных STANDBY (READ_ONLY). Sql Server позволил мне изменить настройку «TRUSTWORTHY», а затем восстановить ее до того, что было раньше. Я проверил, что изменение фактически выгружало домен, посмотрев на результат из SELECT * FROM sys.dm_clr_appdomains;. Милая.
Грейнджер