Além de reiniciar o SQL Server, existe alguma maneira de forçar a reinicialização do SQLCLR AppDomain?

11

Quero forçar o AppDomain que está sendo usado pelo SQLCLR a ser redefinido. Como posso fazer isso além de reiniciar a instância do SQL Server?

Justin Dearing
fonte
Não tenho certeza se você recebe notificações sobre atualizações de respostas, mas atualizei minha resposta com um método ainda mais fácil :).
Solomon Rutzky

Respostas:

6

Sei que isso é um pouco brutal, mas que tal desabilitar o CLR e reativá-lo?

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
Max Vernon
fonte
2
Um detalhe importante sobre esse método é que ele funciona quando executado em um banco de dados STANDBY (somente leitura); todos os outros métodos que tentei não. Eu precisava disso porque uma atualização para um assembly CLR propagou-se normalmente via envio de log para um catálogo STANDBY, mas o AppDomain não foi recarregado - então continuou executando o código da versão antiga do .dll por cerca de um dia.
Granger
@ Granger muito interessante e bom saber :). No entanto, eu consideraria um erro no SQL Server. Convém relatar isso no site do Connect: connect.microsoft.com/SQLServer/Feedback
Solomon Rutzky
1
@srutzky - Obrigado pela sugestão; Espero que eles fechem o relatório como "Não consertam". A configuração é de todo o servidor, não por catálogo (como 'gatilhos aninhados', 'nível de acesso da transmissão de arquivos' etc.). Essa é a lata de minhocas que eu tentaria abrir.
Granger
@ Granger (e Max): Eu não estava claro sobre o que estava dizendo, pensei que era um bug. Eu não estava dizendo que redefinir a configuração "CLR ativado" que causava o descarregamento era um bug. Eu estava dizendo que o ALTER ASSEMBLYpropagado via envio de logs que não recarregou (ou pelo menos descarregou) o Domínio do Aplicativo foi o bug. De qualquer maneira, encontrei um método ainda mais fácil que adicionei à minha resposta aqui. Se você tivesse a capacidade de testar esse novo método, seria ótimo, pois estou muito curioso para ver se ele funciona no cenário de envio de logs que você descreveu.
Solomon Rutzky
8

Existe uma solução mais elegante que não afeta todos os outros assemblies: basta alterar o PERMISSION_SET de um dos assemblies no domínio do aplicativo (os domínios do aplicativo são por usuário).

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

Lembre-se de que você precisará definir o PERMISSION_SET de volta ao que era. Além disso, você precisa acessar um método na montagem antes de alterar o PERMISSION_SET para descarregá-lo; alterar um assembly que não está atualmente carregado em um domínio de aplicativo ativo, mas com outro assembly, não afeta o domínio de aplicativo (os domínios de aplicativo são por DB, por usuário e não por assembly).


ATUALIZAÇÃO
O método descrito acima é a abordagem mais refinada em que apenas descarrega esse domínio de aplicativo. Porém, exige que a montagem possa ser configurada para um dos outros dois níveis. Para montagens marcadas como SAFEsomente será possível se

  • o banco de dados está definido como TRUSTWORTHY ONou
  • o assembly é assinado e um Login, com base em uma chave assimétrica que é baseada na mesma assinatura que o assembly, existe e recebeu EXTERNAL ACCESS ASSEMBLYa UNSAFE ASSEMBLYpermissão ou a permissão

Nesse caso, você pode simplesmente alterar a TRUSTWORTHYconfiguração ONe voltar imediatamente imediatamente OFFe isso descarregará todos os domínios de aplicativo nesse banco de dados específico:

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

Se você tiver apenas um domínio de aplicativo no banco de dados de qualquer maneira (e suspeito que esse seja o caso em 95% ou mais do tempo), os dois métodos descritos aqui têm o mesmo efeito líquido. E nessa situação, o ALTER DATABASEmétodo parece mais simples, pois não requer a especificação de um nome de objeto específico, nem o conhecimento do original PERMISSION_SET.

Além disso, se você tiver apenas um único domínio de aplicativo, o ALTER DATABASEmétodo será mais simples, mesmo no caso em que o banco de dados já esteja definido TRUSTWORTHY ONou você tenha configurado o login da base de chave com a permissão apropriada. Se você estiver usando um logon baseado em chave, poderá definir TRUSTWORTHYcomo ONe OFFnovamente como mencionado acima. Mas se você já tiver TRUSTWORTHYdefinido ON, basta inverter e configurá-lo como OFFe, em seguida, retornar imediatamente para ON:

ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
Solomon Rutzky
fonte
1
A abordagem atualizada funciona em um catálogo de banco de dados STANDBY (READ_ONLY). O SQL Server me permitiu alterar a configuração "CONFIANÇA" e depois restaurá-la para o que era antes. Eu verifiquei que a alteração realmente descarregou o domínio olhando o resultado de SELECT * FROM sys.dm_clr_appdomains;. Doce.
Granger