À part le redémarrage de SQL Server, existe-t-il un moyen de forcer la réinitialisation de l'AppDomain SQLCLR?


11

Je souhaite forcer la réinitialisation de l'AppDomain utilisé par SQLCLR. Comment puis-je faire cela en plus de redémarrer l'instance SQL Server?


Je ne sais pas si vous recevez des notifications sur les mises à jour des réponses, mais j'ai mis à jour ma réponse avec une méthode encore plus simple :).
Solomon Rutzky

Réponses:


6

Je sais que c'est un peu brutal, mais qu'en est-il de désactiver le CLR et de le réactiver?

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
Un détail important de cette méthode est qu'elle fonctionne lorsqu'elle est exécutée sur une base de données STANDBY (lecture seule); toutes les autres méthodes que j'ai essayées ne le font pas. J'en avais besoin car une mise à jour d'un assemblage CLR se propageait normalement via l'envoi de journaux vers un catalogue STANDBY, mais l'AppDomain ne se rechargeait pas --- il a donc continué à exécuter le code de l'ancienne version du .dll pendant environ une journée.
Granger

@Granger très intéressant et bon à savoir :). Cependant, je considérerais qu'il s'agit d'un bogue dans SQL Server. Vous voudrez peut-être signaler cela via le site Connect: connect.microsoft.com/SQLServer/Feedback
Solomon Rutzky

1
@srutzky - Merci pour la suggestion; Je m'attends à ce qu'ils clôturent simplement le rapport comme "ne résoudra pas". Le paramètre est à l'échelle du serveur, pas par catalogue (tout comme les «déclencheurs imbriqués», le «niveau d'accès au filestream», etc.). C'est tout à fait la boîte de vers que j'essaierais d'ouvrir.
Granger

@Granger (et Max): Je ne savais pas trop ce que je disais que je pensais être un bug. Je ne disais pas que la réinitialisation du paramètre "CLR activé" provoquant le déchargement était un bogue. Je disais que la ALTER ASSEMBLYpropagation via l'envoi de journaux qui n'a pas rechargé (ou au moins déchargé) le domaine d'application était le bogue. Quoi qu'il en soit, j'ai trouvé une méthode encore plus simple que j'ai ajoutée à ma réponse ici. Si vous aviez la possibilité de tester cette nouvelle méthode, ce serait formidable car je suis très curieux de voir si cela fonctionne dans le scénario d'envoi de journaux que vous avez décrit.
Solomon Rutzky

8

Il existe une solution plus élégante qui n'affectera pas tous les autres assemblys: modifiez simplement le PERMISSION_SET de l'un des assemblys du domaine d'application (les domaines d'application sont par utilisateur).

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

N'oubliez pas que vous devrez remettre le PERMISSION_SET sur ce qu'il était. De plus, vous devez accéder à une méthode dans l'assembly avant de modifier le PERMISSION_SET pour le décharger; la modification d'un assembly qui n'est pas actuellement chargé dans un domaine d'application actif, mais avec un autre assembly, n'a aucun effet sur le domaine d'application (les domaines d'application sont par base de données, par utilisateur et non par assemblage).


MISE À JOUR
La méthode décrite ci-dessus est l'approche la plus fine où elle ne déchargera qu'un seul domaine d'application. Mais, cela nécessite que l'ensemble puisse être défini sur l'un des deux autres niveaux. Pour les assemblages marqués comme SAFEcela ne sera possible que si

  • la base de données est définie sur TRUSTWORTHY ON, ou
  • l'assembly est signé et une connexion, basée sur une clé asymétrique qui est elle-même basée sur la même signature que l'assembly, existe et a reçu la EXTERNAL ACCESS ASSEMBLYou la UNSAFE ASSEMBLYpermission

Dans ce cas, vous pouvez simplement modifier le TRUSTWORTHYparamètre ON, puis immédiatement à OFFnouveau et cela déchargera tous les domaines d'application dans cette base de données particulière:

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

Si vous n'avez de toute façon qu'un seul domaine d'application (et je soupçonne que c'est le cas à 95% ou plus du temps), les deux méthodes décrites ici ont le même effet net. Et dans cette situation, la ALTER DATABASEméthode semble plus simple car elle ne nécessite pas de spécifier un nom d'objet particulier ni de savoir ce qu'était l'original PERMISSION_SET.

AUSSI, si vous ne disposez que d'un seul domaine d'application, la ALTER DATABASEméthode est plus simple, même dans le cas où la base de données est déjà définie sur TRUSTWORTHY ONou que vous avez configuré la connexion à la base de clés avec l'autorisation appropriée. Si vous utilisez un login par clé vous pouvez définir TRUSTWORTHYà ONpuis à OFFnouveau comme mentionné ci - dessus. Mais si vous l'avez déjà TRUSTWORTHYdéfini ON, inversez-le et définissez-le OFF, puis revenez immédiatement à ON:

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

1
L'approche mise à jour fonctionne sur un catalogue de base de données STANDBY (READ_ONLY). Sql Server m'a permis de modifier le paramètre "TRUSTWORTHY", puis de le restaurer à ce qu'il était auparavant. J'ai vérifié que le changement a effectivement déchargé le domaine en regardant le résultat de SELECT * FROM sys.dm_clr_appdomains;. Sucré.
Granger
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.