Oltre al riavvio di SQL Server, esiste un modo per forzare il ripristino di AppDomain SQLCLR?


11

Voglio forzare il ripristino dell'AppDomain utilizzato da SQLCLR. Come posso farlo oltre a riavviare l'istanza di SQL Server?


Non sono sicuro di ricevere notifiche sugli aggiornamenti delle risposte, ma ho aggiornato la mia risposta con un metodo ancora più semplice :).
Solomon Rutzky,

Risposte:


6

So che è un po 'brutale, ma che dire di disabilitare il CLR e riattivarlo?

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 dettaglio importante di questo metodo è che funziona quando eseguito su un database STANDBY (sola lettura); tutti gli altri metodi che ho provato non lo fanno. Ne avevo bisogno perché un aggiornamento di un assembly CLR si propaga normalmente tramite la distribuzione dei log in un catalogo STANDBY, ma AppDomain non è stato ricaricato --- quindi ha continuato a eseguire il codice dalla vecchia versione del DLL per circa un giorno.
Granger,

@Granger molto interessante e buono a sapersi :). Tuttavia, lo considererei un bug all'interno di SQL Server. Potresti voler segnalarlo tramite il sito Connect: connect.microsoft.com/SQLServer/Feedback
Solomon Rutzky

1
@srutzky - Grazie per il suggerimento; Mi aspetto che chiudano il rapporto come "Non risolto". L'impostazione è a livello di server, non per catalogo (proprio come "trigger nidificati", "livello di accesso filestream", ecc.). È piuttosto la lattina di vermi che avrei cercato di aprire.
Granger,

@Granger (e Max): non ero chiaro su quello che stavo dicendo pensavo fosse un bug. Non stavo dicendo che il ripristino dell'impostazione "CLR abilitato" che causava lo scaricamento fosse un bug. Stavo dicendo che la ALTER ASSEMBLYpropagazione tramite log shipping che non ha ricaricato (o almeno scaricato) il dominio app era il bug. Ad ogni modo, ho trovato un metodo ancora più semplice che ho aggiunto alla mia risposta qui. Se avessi la possibilità di testare questo nuovo metodo sarebbe fantastico, dato che sono molto curioso di vedere se funziona nello scenario di spedizione dei log che hai descritto.
Solomon Rutzky,

8

Esiste una soluzione più elegante che non influirà su tutti gli altri assembly: basta cambiare PERMISSION_SET di uno degli assembly nel dominio dell'app (i domini dell'app sono per utente).

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

Ricorda solo che dovrai riportare PERMISSION_SET su quello che era. Inoltre, è necessario accedere a un metodo nell'assemblaggio prima di modificare PERMISSION_SET per scaricarlo; la modifica di un assembly che non è attualmente caricato in un dominio di app che è attivo, ma con un altro assembly, non ha alcun effetto sul dominio di app (i domini di app sono per DB, per utente, non per assembly).


AGGIORNAMENTO
Il metodo sopra descritto è l'approccio più dettagliato in cui scaricherà solo un dominio app. Tuttavia, richiede che l'assembly possa essere impostato su uno degli altri due livelli. Per gli assiemi contrassegnati come SAFEsarà possibile solo se uno dei due

  • il database è impostato su TRUSTWORTHY ONo
  • l'assembly viene firmato ed esiste un Login, basato su una chiave asimmetrica che si basa sulla stessa firma dell'assembly, a cui è stata concessa EXTERNAL ACCESS ASSEMBLYl' UNSAFE ASSEMBLYautorizzazione o

In questo caso puoi semplicemente cambiare l' TRUSTWORTHYimpostazione ONe poi immediatamente di OFFnuovo indietro e questo scaricherà tutti i domini app in quel particolare database:

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

Se hai comunque un solo dominio app nel database (e sospetto che questo sia il caso del 95% o più del tempo), entrambi i metodi qui descritti hanno lo stesso effetto netto. E in quella situazione, il ALTER DATABASEmetodo sembra più semplice in quanto non richiede di specificare un nome di oggetto particolare né di sapere quale fosse l'originale PERMISSION_SET.

ANCHE, se si dispone di un solo dominio app, il ALTER DATABASEmetodo è più semplice anche nel caso in cui il database sia già impostato TRUSTWORTHY ONo si sia configurato l'accesso con base di chiavi con l'autorizzazione appropriata. Se si utilizza un accesso basato su chiave, è possibile impostare TRUSTWORTHYsu ONe poi di OFFnuovo come indicato sopra. Ma se hai già TRUSTWORTHYimpostato su ON, quindi capovolgilo e impostalo su OFFe quindi immediatamente su ON:

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

1
L'approccio aggiornato funziona su un catalogo di database STANDBY (READ_ONLY). Sql Server mi ha permesso di modificare l'impostazione "TRUSTWORTHY", quindi ripristinarla come era prima. Ho verificato che la modifica ha effettivamente scaricato il dominio osservando il risultato da SELECT * FROM sys.dm_clr_appdomains;. Dolce.
Granger,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.