Czy oprócz ponownego uruchomienia programu SQL Server można wymusić zresetowanie aplikacji AppDomain SQLCLR?

11

Chcę wymusić resetowanie AppDomain przez SQLCLR. Jak mogę to zrobić oprócz zrestartowania instancji SQL Server?

Justin Dearing
źródło
Nie jestem pewien, czy otrzymujesz powiadomienia o aktualizacjach odpowiedzi, ale zaktualizowałem odpowiedź jeszcze łatwiejszą metodą :).
Solomon Rutzky

Odpowiedzi:

6

Wiem, że to trochę brutalne, ale co z wyłączeniem CLR i ponownym włączeniem?

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
źródło
2
Jednym ważnym szczegółem tej metody jest to, że działa ona w przypadku wykonania jej w bazie danych STANDBY (tylko do odczytu); wszystkie inne metody, których próbowałem nie. Potrzebowałem tego, ponieważ aktualizacja zestawu CLR propagowała się normalnie poprzez wysyłanie dziennika do katalogu STANDBY, ale AppDomain nie przeładował się --- więc kontynuował uruchamianie kodu ze starej wersji .dll przez około jeden dzień.
Granger
@Granger bardzo ciekawy i dobrze wiedzieć :). Jednak uważam, że błąd w SQL Server. Możesz to zgłosić za pośrednictwem strony Connect: connect.microsoft.com/SQLServer/Feedback
Solomon Rutzky
1
@srutzky - Dzięki za sugestię; Oczekuję, że po prostu zamkną raport jako „Nie naprawią”. Ustawienie dotyczy całego serwera, a nie poszczególnych katalogów (podobnie jak „wyzwalacze zagnieżdżone”, „poziom dostępu do strumienia” itp.). To całkiem puszka robaków, które chciałbym otworzyć.
Granger
@Granger (i Max): Nie miałem jasności co do tego, co mówiłem, że uważam za błąd. Nie mówiłem, że resetowanie ustawienia „CLR Enabled” powodujące rozładowanie było błędem. Mówiłem, że błąd ALTER ASSEMBLYpropagowany przez wysyłanie dziennika, który nie przeładował (lub przynajmniej rozładował) domeny aplikacji. Tak czy inaczej, znalazłem jeszcze łatwiejszą metodę, którą dodałem tutaj do mojej odpowiedzi. Jeśli miałbyś możliwość przetestowania tej nowej metody, byłoby świetnie, ponieważ jestem bardzo ciekawy, czy działa ona w opisanym scenariuszu wysyłania dziennika.
Solomon Rutzky
8

Istnieje bardziej eleganckie rozwiązanie, które nie wpłynie na wszystkie inne zestawy: wystarczy zmienić PERMISSION_SET jednego z zestawów w domenie aplikacji (domeny aplikacji są na użytkownika).

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

Pamiętaj tylko, że musisz ustawić PERMISSION_SET z powrotem na to, co było. Musisz także uzyskać dostęp do metody w zespole, zanim zmiana PERMISSION_SET spowoduje jej rozładowanie; zmiana zestawu, który nie jest aktualnie ładowany do domeny aplikacji, która jest aktywna, ale z innym zestawem, nie ma wpływu na domenę aplikacji (Domeny aplikacji są na DB, na użytkownika, a nie na zestaw).


AKTUALIZACJA
Opisana powyżej metoda jest najbardziej szczegółowym podejściem, w którym zwalnia tylko jedną domenę aplikacji. Wymaga to jednak ustawienia zestawu na jednym z dwóch pozostałych poziomów. W przypadku zespołów oznaczonych jako SAFEbędzie to możliwe tylko wtedy, gdy jedno z nich

  • baza danych jest ustawiona na TRUSTWORTHY ON, lub
  • zespół jest podpisana i logowania na podstawie klucza asymetrycznego, który sam jest oparty na tym samym podpisu jako zespół, istnieje i została udzielona albo EXTERNAL ACCESS ASSEMBLYczy UNSAFE ASSEMBLYzezwolenie

W takim przypadku możesz po prostu zmienić TRUSTWORTHYustawienie, ONa następnie natychmiast OFFponownie powrócić, a to zwolni wszystkie Domeny aplikacji w tej konkretnej bazie danych:

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

Jeśli i tak masz tylko jedną domenę aplikacji w bazie danych (i podejrzewam, że tak jest w 95% lub więcej przypadków), wówczas obie opisane tutaj metody mają ten sam efekt netto. W tej sytuacji ALTER DATABASEmetoda wydaje się prostsza, ponieważ nie wymaga podania nazwy konkretnego obiektu ani znajomości oryginalnego obiektu PERMISSION_SET.

RÓWNIEŻ, jeśli masz tylko jedną domenę aplikacji, ALTER DATABASEmetoda jest prostsza, nawet w przypadku, gdy baza danych jest już ustawiona na TRUSTWORTHY ONlub skonfigurowano logowanie do bazy kluczy z odpowiednim uprawnieniem. Jeśli używasz logowania opartego na kluczach, możesz ustawić TRUSTWORTHYna, ONa następnie OFFponownie, jak wspomniano powyżej. Ale jeśli już TRUSTWORTHYustawiłeś ON, po prostu odwróć go i ustaw na, OFFa następnie natychmiast z powrotem na ON:

ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
Solomon Rutzky
źródło
1
Zaktualizowane podejście działa w katalogu bazy danych STANDBY (TYLKO DO ODCZYTU). Serwer SQL pozwolił mi zmienić ustawienie „TRUSTWORTHY”, a następnie przywrócić to, co było wcześniej. Sprawdziłem, czy zmiana faktycznie zwolniła domenę, patrząc na wynik z SELECT * FROM sys.dm_clr_appdomains;. Słodkie.
Granger,