Architektura integrace CLR – Hostované prostředí CLR
platí pro:SQL Serverazure SQL Managed Instance
Integrace SQL Serveru s modulem CLR (Common Language Runtime) rozhraní .NET Framework umožňuje programátorům databází používat jazyky, jako jsou C#, Visual Basic .NET a Visual C++. Funkce, uložené procedury, triggery, datové typy a agregace patří mezi druhy obchodní logiky, které programátoři můžou psát s těmito jazyky.
CLR obsahuje paměť, preemptivní vlákno, služby metadat (reflexe typu), ověřitelnost kódu a zabezpečení přístupu kódu. CLR používá metadata k vyhledání a načtení tříd, rozložení instancí v paměti, překlad volání metod, generování nativního kódu, vynucování zabezpečení a nastavení hranic kontextu běhu.
CLR a SQL Server se liší v prostředích za běhu způsobem, jakým zpracovávají paměť, vlákna a synchronizaci. Tento článek popisuje způsob, jakým jsou tyto dvě doby spuštění integrované, aby všechny systémové prostředky byly spravovány jednotně. Tento článek také popisuje způsob, jakým jsou integrované zabezpečení přístupu kódu CLR (CAS) a zabezpečení SQL Serveru, aby poskytovalo spolehlivé a zabezpečené spouštěcí prostředí pro uživatelský kód.
Základní koncepty architektury CLR
V rozhraní .NET Framework program píše v jazyce vysoké úrovně, který implementuje třídu definující její strukturu (například pole nebo vlastnosti třídy) a metody. Některé z těchto metod mohou být statické funkce. Kompilace programu vytvoří soubor označovaný jako sestavení, které obsahuje zkompilovaný kód ve společném zprostředkujícím jazyce (CIL) a manifest, který obsahuje všechny odkazy na závislá sestavení.
Poznámka
Sestavení jsou zásadním prvkem architektury CLR. Jedná se o jednotky balení, nasazení a správy verzí kódu aplikace v rozhraní .NET Framework. Pomocí sestavení můžete nasadit kód aplikace uvnitř databáze a poskytnout jednotný způsob správy, zálohování a obnovení kompletních databázových aplikací.
Manifest sestavení obsahuje metadata o sestavení, popisující všechny struktury, pole, vlastnosti, třídy, vztahy dědičnosti, funkce a metody definované v programu. Manifest vytvoří identitu sestavení, určuje soubory, které tvoří implementaci sestavení, určuje typy a prostředky, které tvoří sestavení, položce závislostí kompilace na jiných sestaveních a určuje sadu oprávnění vyžadovaných pro správné spuštění sestavení. Tyto informace se používají za běhu k řešení odkazů, vynucení zásad vazby verzí a ověření integrity načtených sestavení.
Rozhraní .NET Framework podporuje vlastní atributy pro přidávání poznámek ke třídám, vlastnostem, funkcím a metodám s dalšími informacemi, které aplikace může zachytit v metadatech. Všechny kompilátory rozhraní .NET Framework využívají tyto poznámky bez interpretace a ukládají je jako metadata sestavení. Tyto poznámky lze zkoumat stejným způsobem jako jakákoli jiná metadata.
Spravovaný kód se provádí v CLR, nikoli přímo operačním systémem. Aplikace spravovaného kódu získávají služby CLR, jako je automatické uvolňování paměti, kontrola typů za běhu a podpora zabezpečení. Tyto služby pomáhají zajistit jednotné chování aplikací spravovaného kódu nezávisle na platformě a jazyce.
Cíle návrhu integrace CLR
Když se uživatelský kód spustí v prostředí hostované v CLR na SQL Serveru (označované jako integrace CLR), použijí se následující cíle návrhu:
Spolehlivost (bezpečnost)
Uživatelský kód by neměl být povolen k provádění operací, které by mohly ohrozit integritu procesu databázového stroje, jako je například odeslání zprávy s žádostí o odpověď uživatele nebo ukončení procesu. Uživatelský kód by neměl být schopen přepsat vyrovnávací paměti databázového stroje ani interní datové struktury.
Škálovatelnost
SQL Server a CLR mají různé interní modely pro plánování a správu paměti. SQL Server podporuje kooperativní model bez preemptivního vlákna, ve kterém vlákna dobrovolně poskytují provádění pravidelně nebo když čekají na zámky nebo vstupně-výstupní operace. CLR podporuje preemptivní model vláken. Pokud uživatelský kód spuštěný uvnitř SQL Serveru může přímo volat primitiva vláken operačního systému, neintegruje se dobře do plánovače úloh SQL Serveru a může snížit škálovatelnost systému. MODUL CLR nerozlišuje mezi virtuální a fyzickou pamětí, ale SQL Server přímo spravuje fyzickou paměť a je nutný k použití fyzické paměti v rámci konfigurovatelného limitu.
Různé modely pro správu vláken, plánování a správy paměti představují výzvu integrace pro systém pro správu relačních databází (RDBMS), který se škáluje tak, aby podporoval tisíce souběžných uživatelských relací. Architektura by měla zajistit, aby škálovatelnost systému nebyla ohrožena uživatelským kódem volajícím aplikační programovací rozhraní (API) pro přímé podprocesování, paměť a synchronizaci.
Bezpečnost
Uživatelský kód spuštěný v databázi musí při přístupu k databázovým objektům, jako jsou tabulky a sloupce, dodržovat pravidla ověřování a autorizace SQL Serveru. Správci databází by navíc měli mít možnost řídit přístup k prostředkům operačního systému, jako jsou soubory a síťový přístup, z uživatelského kódu spuštěného v databázi. Tento postup je důležitý jako spravované programovací jazyky (na rozdíl od nespravované jazyky, jako je Transact-SQL), poskytují rozhraní API pro přístup k těmto prostředkům. Systém musí poskytnout bezpečný způsob, jak uživatelský kód získat přístup k prostředkům počítače mimo proces databázového stroje. Další informace najdete v tématu zabezpečení integrace CLR.
Představení
Spravovaný uživatelský kód spuštěný v databázovém stroji by měl mít výpočetní výkon srovnatelný se stejným kódem spuštěným mimo server. Přístup k databázi ze spravovaného uživatelského kódu není tak rychlý jako nativní transact-SQL. Další informace najdete v tématu Výkon architektury integrace CLR.
Služby CLR
CLR poskytuje několik služeb, které pomáhají dosáhnout cílů návrhu integrace CLR s SQL Serverem.
Ověření bezpečnosti typů
Typově bezpečný kód je kód, který přistupuje ke strukturám paměti pouze dobře definovanými způsoby. Například vzhledem k platnému odkazu na objekt může kód typu bezpečný přistupovat k paměti při pevných posunech odpovídajících skutečným členům pole. Pokud však kód přistupuje k paměti při libovolných posunech uvnitř nebo mimo rozsah paměti, který patří do objektu, pak není typově bezpečný. Při načtení sestavení v CLR před kompilací CIL pomocí kompilace za běhu (JIT) modul runtime provede fázi ověření, která zkoumá kód, aby určil jeho typ-bezpečnost. Kód, který úspěšně projde tímto ověřením, se nazývá ověřitelný typově bezpečný kód.
Domény aplikací
CLR podporuje pojem domény aplikace jako spouštěcí zóny v rámci hostitelského procesu, kde je možné načíst a spustit sestavení spravovaného kódu. Hranice domény aplikace poskytuje izolaci mezi sestaveními. Sestavení jsou izolovaná z hlediska viditelnosti statických proměnných a datových členů a možnosti dynamického volání kódu. Domény aplikací jsou také mechanismus načítání a uvolňování kódu. Kód lze uvolnit z paměti pouze uvolněním domény aplikace. Další informace najdete v tématu domény aplikací a zabezpečení integrace CLR.
Zabezpečení přístupu kódu (CAS)
Systém zabezpečení CLR poskytuje způsob, jak řídit, jaké druhy operací může spravovaný kód provádět přiřazením oprávnění ke kódu. Přístupová oprávnění ke kódu se přiřazují na základě identity kódu (například podpis sestavení nebo původ kódu).
Modul CLR poskytuje zásady pro celý počítač, které může nastavit správce počítače. Tato zásada definuje udělení oprávnění pro jakýkoli spravovaný kód spuštěný na počítači. Kromě toho existují zásady zabezpečení na úrovni hostitele, které můžou používat hostitelé, jako je SQL Server, k určení dalších omezení spravovaného kódu.
Pokud spravované rozhraní API v rozhraní .NET Framework zveřejňuje operace s prostředky, které jsou chráněné oprávněním pro přístup ke kódu, vyžaduje rozhraní API toto oprávnění před přístupem k prostředku. Tato poptávka způsobí, že systém zabezpečení CLR aktivuje komplexní kontrolu každé jednotky kódu (sestavení) v zásobníku volání. Přístup k prostředku je udělen pouze v případě, že má celý řetěz volání oprávnění.
Možnost generovat spravovaný kód dynamicky pomocí rozhraní Reflection.Emit
API není podporována v prostředí hostovaném modulem CLR na SQL Serveru. Takový kód by neměl oprávnění CAS ke spuštění, a proto by v době běhu selhal. Další informace naleznete v tématu CLR integration Code Access Security.
Atributy ochrany hostitele (HPA)
CLR poskytuje mechanismus pro přidávání poznámek ke spravovaným rozhraním API, která jsou součástí rozhraní .NET Framework s určitými atributy, které by mohly být zajímavé pro hostitele modulu CLR. Mezi příklady takových atributů patří:
SharedState
, což označuje, jestli rozhraní API zpřístupňuje schopnost vytvářet nebo spravovat sdílený stav (například statická pole tříd).Synchronization
, který označuje, zda rozhraní API zpřístupňuje schopnost provádět synchronizaci mezi vlákny.ExternalProcessMgmt
, který označuje, jestli rozhraní API zpřístupňuje způsob řízení hostitelského procesu.
Vzhledem k těmto atributům může hostitel zadat seznam hpA, například atribut SharedState
, který by se měl v hostovaném prostředí nepovolit. V tomto případě CLR odmítne pokusy uživatelského kódu volat rozhraní API, která jsou anotována hpA v seznamu zakázaných. Další informace najdete v tématu Atributy ochrany hostitele a programování integrace CLR.
Jak SQL Server a CLR spolupracují
Tato část popisuje, jak SQL Server integruje vlákna, plánování, synchronizaci a modely správy paměti SYSTÉMU SQL Server a CLR. Konkrétně tato část zkoumá integraci s ohledem na škálovatelnost, spolehlivost a cíle zabezpečení. SQL Server v podstatě funguje jako operační systém modulu CLR, když je hostovaný uvnitř SQL Serveru. CLR volá rutiny nízké úrovně implementované SQL Serverem pro vlákna, plánování, synchronizaci a správu paměti. Tyto rutiny jsou stejné primitivy, které používá zbytek modulu SQL Serveru. Tento přístup poskytuje několik výhod škálovatelnosti, spolehlivosti a zabezpečení.
Škálovatelnost: Běžné dělení na vlákna, plánování a synchronizaci
CLR volá rozhraní API SQL Serveru pro vytváření vláken, a to jak pro spouštění uživatelského kódu, tak pro vlastní interní použití. Aby bylo možné synchronizovat více vláken, CLR volá synchronizační objekty SQL Serveru. Tento postup umožňuje plánovači SQL Serveru naplánovat další úlohy, když vlákno čeká na objekt synchronizace. Například když CLR zahájí uvolňování paměti, všechny jeho vlákna čekají na dokončení uvolňování paměti. Vzhledem k tomu, že vlákna CLR a objekty synchronizace, na které čekají, jsou známé plánovači SQL Serveru, může SQL Server naplánovat vlákna, na kterých běží jiné databázové úlohy, které nezahrnují CLR. To také umožňuje SQL Serveru rozpoznat zablokování, které zahrnuje zámky převzaté objekty synchronizace CLR a používají tradiční techniky pro odstranění zablokování.
Spravovaný kód běží na SQL Serveru předem. Plánovač SQL Serveru má schopnost detekovat a zastavit vlákna, která se po dlouhou dobu nevyvolila. Schopnost připojit vlákna CLR k podprocesům SQL Serveru znamená, že plánovač SQL Serveru dokáže identifikovat "runaway" vlákna v CLR a spravovat jejich prioritu. Taková spuštěná vlákna jsou pozastavena a vrácena do fronty. Vlákna, která jsou opakovaně identifikována jako spuštěná vlákna, nesmí běžet po danou dobu, aby bylo možné spustit další pracovní procesy.
Existují situace, kdy se dlouhotrvající spravovaný kód automaticky vyvolá a některé situace, kdy ne. V následujících situacích se dlouhotrvající spravovaný kód automaticky vyvolá:
- Pokud kód volá operační systém SQL (například k dotazování dat)
- Pokud je k aktivaci uvolňování paměti přiděleno dostatek paměti
- Pokud kód přejde do preemptivního režimu voláním funkcí operačního systému.
Kód, který neprovádí žádnou z těchto akcí, například těsné smyčky, které obsahují pouze výpočty, automaticky nevyvolá plánovač, což může vést k dlouhým čekáním na jiné úlohy v systému. V těchto situacích je na vývojáři, aby explicitně poskytli volání funkce System.Thread.Sleep()
rozhraní .NET Framework nebo explicitním zadáním preemptivního režimu s System.Thread.BeginThreadAffinity()
v libovolné části kódu, které se očekávají dlouho. Následující příklady kódu ukazují, jak ručně získat pomocí každé z těchto metod.
Příklady
Ruční výnos do plánovače SOS
for (int i = 0; i < Int32.MaxValue; i++)
{
// *Code that does compute-heavy operation, and does not call into
// any OS functions.*
// Manually yield to the scheduler regularly after every few cycles.
if (i % 1000 == 0)
{
Thread.Sleep(0);
}
}
Použití ThreadAffinity ke spuštění preemptively
V tomto příkladu kód CLR běží v preemptivním režimu v rámci BeginThreadAffinity
a EndThreadAffinity
.
Thread.BeginThreadAffinity();
for (int i = 0; i < Int32.MaxValue; i++)
{
// *Code that does compute-heavy operation, and does not call into
// any OS functions.*
}
Thread.EndThreadAffinity();
Škálovatelnost: Běžná správa paměti
CLR volá primitiva SQL Serveru pro přidělování a uvolnění paměti. Vzhledem k tomu, že paměť používaná clr je zohledněny v celkovém využití paměti systému, SQL Server může zůstat v rámci nakonfigurovaných limitů paměti a zajistit, aby modul CLR a SQL Server vzájemně nekokurovaly pro paměť. SQL Server může také odmítnout požadavky na paměť CLR, pokud je systémová paměť omezena, a požádat CLR o snížení využití paměti v případě, že jiné úlohy potřebují paměť.
Spolehlivost: Domény aplikací a neopravitelné výjimky
Když spravovaný kód v rozhraních API rozhraní .NET Framework narazí na kritické výjimky, jako je nedostatek paměti nebo přetečení zásobníku, není vždy možné se z těchto selhání zotavit a zajistit konzistentní a správnou sémantiku pro jejich implementaci. Tato rozhraní API vyvolávají výjimku přerušení vlákna v reakci na tato selhání.
Při hostované na SQL Serveru se takové přerušení vláken zpracovává následujícím způsobem: CLR zjistí jakýkoli sdílený stav v doméně aplikace, ve které dojde k přerušení vlákna. CLR to zjistí kontrolou přítomnosti synchronizačních objektů. Pokud je v doméně aplikace sdílený stav, je samotná doména aplikace uvolněna. Uvolnění domény aplikace zastaví databázové transakce, které jsou aktuálně spuštěné v této doméně aplikace. Vzhledem k tomu, že přítomnost sdíleného stavu může rozšířit účinek takových kritických výjimek na uživatelské relace kromě těch, které tuto výjimku aktivují, sql Server a CLR provedly kroky ke snížení pravděpodobnosti sdíleného stavu. Další informace naleznete v tématu rozhraní .NET Framework.
Zabezpečení: Sady oprávnění
SQL Server umožňuje uživatelům určit požadavky na spolehlivost a zabezpečení pro kód nasazený do databáze. Při nahrání sestavení do databáze může autor sestavení určit jednu ze tří sad oprávnění pro toto sestavení: SAFE
, EXTERNAL_ACCESS
a UNSAFE
.
Funkčnost | SAFE |
EXTERNAL_ACCESS |
UNSAFE |
---|---|---|---|
Code Access Security |
Spustit pouze | Spuštění a přístup k externím prostředkům | Neomezený |
Programming model restrictions |
Ano | Ano | Žádná omezení |
Verifiability requirement |
Ano | Ano | Ne |
Ability to call native code |
Ne | Ne | Ano |
SAFE
je nejspolehlivější a nejbezpečnější režim s přidruženými omezeními z hlediska povoleného programovacího modelu.
SAFE
sestavení mají dostatečná oprávnění ke spuštění, provádění výpočtů a přístupu k místní databázi.
SAFE
sestavení musí být ověřitelně typově bezpečná a nesmí volat nespravovaný kód.
UNSAFE
je určen pro vysoce důvěryhodný kód, který může vytvářet pouze správci databáze. Tento důvěryhodný kód nemá žádná omezení zabezpečení přístupu kódu a může volat nespravovaný (nativní) kód.
EXTERNAL_ACCESS
poskytuje zprostředkující možnost zabezpečení, která umožňuje kódu přistupovat k prostředkům externím databázím, ale přesto mít záruky spolehlivosti SAFE
.
SQL Server používá vrstvu zásad CAS na úrovni hostitele k nastavení zásady hostitele, která uděluje jednu ze tří sad oprávnění na základě sady oprávnění uložené v katalogech SQL Serveru. Spravovaný kód spuštěný v databázi vždy získá jednu z těchto sad oprávnění pro přístup ke kódu.
Omezení programovacího modelu
Programovací model spravovaného kódu v SQL Serveru zahrnuje psaní funkcí, postupů a typů, které obvykle nevyžadují použití stavu uchovávaného ve více vyvolání nebo sdílení stavu napříč několika uživatelskými relacemi. Jak je popsáno výše, přítomnost sdíleného stavu může způsobit kritické výjimky, které ovlivňují škálovatelnost a spolehlivost aplikace.
Vzhledem k těmto aspektům nedoporučujeme používat statické proměnné a statické datové členy tříd používaných v SQL Serveru. Pro SAFE
a EXTERNAL_ACCESS
sestavení SQL Server zkontroluje metadata sestavení v CREATE ASSEMBLY
čase a selže při vytváření těchto sestavení, pokud najde použití statických datových členů a proměnných.
SQL Server také zakáže volání rozhraní API rozhraní .NET Framework, která jsou opatřena poznámkami SharedState
, Synchronization
a ExternalProcessMgmt
atributy ochrany hostitele. To brání SAFE
a EXTERNAL_ACCESS
sestavení v volání všech rozhraní API, která umožňují stav sdílení, provádějí synchronizaci a ovlivňují integritu procesu SQL Serveru. Další informace najdete v tématu omezení programovacího modelu integrace CLR.