Impostare una libreria di repository di procedure / funzioni memorizzata CLR centrale per procs memorizzati interni in altri database da usare?


17

Vorrei usare il codice che ho sviluppato in C # CLR per essere utilizzato in tutti i database sul sistema in modo da non dover impostare ognuno su affidabile e accendere CLR e mantenere un mucchio dello stesso codice all'interno di ciascuno .

C'è un modo migliore per farlo da un punto di vista amministrativo e di sicurezza? Le funzioni CLR sono molto semplici come interruttori di stringa, convalida e-mail, url en / decode, base64, ecc. Vorrei che solo lo schema dbo in ciascun database fosse in grado di accedere alle funzioni.

  1. C'è un modo semplice per farlo?
  2. Inoltre, non sono chiaro se la DLL CLR sia incorporata e se sposto il database, esso viene taggato o devo spostare anche la DLL.

Grazie


1
Ok suona bene. Finché non sento grilli dal silenzio morto sulla domanda. Ho sempre avuto fortuna con StackOverflow
Alex Erwin,

1
dba.se è meno frenetico di SO, ma sono fiducioso che riceverai una buona attenzione su una domanda come questa entro circa un giorno. Sei felice di essere paziente così a lungo?
Jack Douglas,

Lol, la pazienza è una virtù. Ne ho una discreta quantità, e la domanda stessa, penso, la SM dovrebbe rispondere. Cosa succede se si è un host di SQL Server che desidera esporre alcune funzioni utili ma non avere il server aperto a CLR in piena forza?
Alex Erwin,

Risposte:


8

Nella nostra azienda abbiamo la configurazione esatta. Quando si crea un assembly CLR, una rappresentazione binaria dell'assembly viene archiviata nel database in cui lo si crea. Ciò consente di portarlo con sé (e persino di eseguirne lo script) in caso di spostamento del database in qualsiasi momento.

Un paio di mesi fa il nostro data center è stato allagato, riempiendo diversi server pieni d'acqua. Quando li ho ricostruiti ho usato solo i backup del db che erano stati presi la sera prima. Finora non abbiamo avuto problemi .. (tocca il legno!)

Non sono sicuro che questa sia la cosa giusta da fare dal punto di vista della sicurezza, ma il modo in cui concediamo l'accesso ai proc di CLR ecc. È quello di creare un ruolo all'interno del database condiviso e quindi aggiungere gli utenti di altri database a quel ruolo. Il ruolo viene quindi concesso eseguire sui proc CLR.

Potrebbero esserci problemi di accesso se il CLR sta provando a fare cose come accedere alle risorse al di fuori del database in cui è contenuto, ma è possibile impostare l'autorizzazione sull'assembly quando lo si crea. Il link seguente contiene molte più informazioni riguardo alle autorizzazioni di quante ne possa spiegare qui:

http://msdn.microsoft.com/en-us/library/ms345101.aspx

Spero che questo ti aiuti.


6

Il file binario dell'assembly viene archiviato come un BLOB nel database, quindi viene portato ovunque il database vada. CLR è abilitato solo sul caso - non sono presenti impostazioni di database specifici per questo.

In ogni caso, perché stai cercando di farlo?

(Non sto cercando di essere polemico; voglio solo sentire i motivi coinvolti, perché forse il problema potrebbe essere risolto in un modo diverso che soddisfa le tue esigenze.)


Non c'è modo di farlo facilmente, se non per mettere l'assembly in un database condiviso.

Detto questo, penso che sia vantaggioso abbracciare l'architettura incentrata sul database, a meno che non ci sia una situazione particolare che abbia ragioni molto convincenti per centralizzare. Il motivo è che mettere l'assembly (o qualsiasi altra cosa) al di fuori del database crea una dipendenza nel proprio ambiente. Questo è esattamente l'approccio opposto adottato da Microsoft con i database contenuti a partire da SQL Server 2012.

  • Quando si inizia a utilizzare funzionalità come la replica o il clustering, questa dipendenza può potenzialmente aggiungere un'enorme quantità di complessità alla distribuzione, ma anche alle procedure di risoluzione dei problemi e di failover.

  • Questa architettura è molto meno ovvia per le persone che non hanno familiarità con il sistema (vale a dire, è meno auto-rilevabile e meno auto-documentato).

  • Se finisci per richiedere una sicurezza diversa in database diversi o qualsiasi cosa implichi una variazione, sei in un mondo ferito.

  • Se questi database vengono distribuiti ai clienti (sembra che non lo saranno, ma lo dirò per completezza), ciò aggiunge complessità alla procedura di distribuzione, manutenzione e risoluzione dei problemi.

  • Poiché tutti i database condividono questo codice, se vengono introdotti (o corretti errori), ciò potrebbe potenzialmente interrompere tutte le applicazioni che si basano sui database. Test unitari completi sarebbero indispensabili.

Se si dispone di più database che richiedono la stessa funzionalità, esistono altri modi per ridurre il numero di duplicati coinvolti, che presumo sia il punto dell'esercizio. Anche un assembly CLR abbastanza complesso non occuperà molto spazio di archiviazione fisico rispetto ai dati nel database stesso (quasi sempre), quindi non lo considero un argomento valido a meno che tu non abbia letteralmente migliaia di piccoli database che hanno bisogno di questo montaggio.

Ciò che è possibile fare è modificare altre parti della procedura di distribuzione per questi database per ridurre la duplicazione di origine. Ad esempio, compilare e distribuire l'assembly dalla posizione comune del codice CLR nel controllo del codice sorgente. In alternativa, creare uno script che distribuisce lo stesso assembly nei database. Automatizza questa parte delle cose il più possibile e non sarà un grosso problema.

Concordo sul fatto che ciò che sto suggerendo è un compromesso, perché ci sarà ancora qualche duplicazione, ma questo deve essere bilanciato con gli aspetti negativi coinvolti nell'implementazione di un'architettura che non segue lo standard prescritto. Solo tu puoi decidere cosa è giusto per il tuo ambiente.


Vedo il tuo punto con la possibilità di rompere le cose, tuttavia è semplificare l'implementazione del codice. Nessun esercito di sviluppatori qui. Solo io. Ne ho comunque altri che utilizzano il database, quindi devo assicurarmi che le funzioni siano inaccessibili a meno che non vengano utilizzate dalle procedure memorizzate che definisco.
Alex Erwin,

1

Come affermano correttamente le altre due risposte, gli assembly vengono caricati in un determinato database e non sono a livello di sistema (anche se sono abbastanza certo che il assembly_idvalore sia univoco a livello di sistema). Ciò significa che vengono sottoposti a backup e ripristinati con ogni database in cui sono caricati.

Inoltre, l' impostazione enabled/ disableddi CLR Integration(via sp_configure) è a livello di sistema. Come nota a margine, tale impostazione è solo per la funzionalità CLR creata dall'utente; CLR in generale è sempre abilitato in quanto determinate funzionalità integrate dipendono da esso.

Detto questo, mentre le altre due risposte qui fanno punti validi, quei punti non sono specifici di SQLCLR e non si fa menzione dei fattori nel prendere questa decisione che sono specifici del codice SQLCLR. Ci sono problemi di memoria da considerare se si distribuisce il codice in ogni singolo database (supponendo che si disponga di molti database), potenziali problemi di contesa di risorse, potenziali problemi di sicurezza, ecc.

Ho fornito quello che dovrebbe essere un elenco completo di cose da tenere a mente, in particolare per il codice SQLCLR, quando si decide tra un database centralizzato e la distribuzione di singoli database. Anziché duplicare l'elenco qui, vedere la seguente risposta (anche qui su DBA.SE):

Come utilizzare al meglio la funzione CLR dal punto di vista delle prestazioni (ripetere all'interno di ciascun DB o avere una funzione generale)?

Inoltre, su una nota correlata, mi chiedo perché qualsiasi database è impostato su TRUSTWORTHY ON. Le funzionalità indicate nella domanda (ovvero "interruttori di stringa, convalida e-mail, url en / decode, base64, ecc") sono tutte possibili all'interno di un SAFEassembly. Non utilizzare i valori EXTERNAL_ACCESSo UNSAFEperission_set a meno che non sia assolutamente necessario. E se è necessario per un certo numero di funzioni, quelle dovrebbero essere in un assieme separato che contiene solo SAFEcodice in modo tale che tutte le funzioni scalari che non accedono ai dati e siano contrassegnate come IsDeterministic = truesaranno in grado di sfruttare il vantaggio in termini di prestazioni di essere in grado di partecipare a piani paralleli.

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.