Megosztás a következőn keresztül:


CLR integrációs architektúra – CLR által üzemeltetett környezet

A következőkre vonatkozik:SQL ServerFelügyelt Azure SQL-példány

Az SQL Server a .NET-keretrendszer közös nyelvi futtatókörnyezetével (CLR) való integrációja lehetővé teszi, hogy az adatbázis-programozók olyan nyelveket használjanak, mint a C#, a Visual Basic .NET és a Visual C++. A függvények, a tárolt eljárások, az eseményindítók, az adattípusok és az összesítések azon üzleti logikák közé tartoznak, amelyeket a programozók e nyelvekkel írhatnak.

A CLR a szeméttel összegyűjtött memóriát, a megelőző szálkezelést, a metaadat-szolgáltatásokat (típusvisszatükrözést), a kód ellenőrizhetőségét és a kódhozzáférés biztonságát tartalmazza. A CLR metaadatokat használ az osztályok megkereséséhez és betöltéséhez, a példányok memóriabeli elhelyezéséhez, metódushívások feloldásához, natív kód létrehozásához, a biztonság kikényszerítéséhez és a futásidejű környezet határainak beállításához.

A CLR és az SQL Server futásidejű környezetekként eltérnek a memória, a szálak és a szinkronizálás kezelésének módjától. Ez a cikk bemutatja, hogyan integrálható ez a két futtatási idő, hogy az összes rendszererőforrás egységesen legyen kezelve. Ez a cikk azt is ismerteti, hogyan integrálható a CLR-kódhozzáférési biztonság (CAS) és az SQL Server biztonsága a felhasználói kód megbízható és biztonságos végrehajtási környezetének biztosítása érdekében.

A CLR-architektúra alapfogalmai

A .NET-keretrendszerben a programozó egy magas szintű nyelven ír, amely egy olyan osztályt implementál, amely meghatározza annak szerkezetét (például az osztály mezőit vagy tulajdonságait) és metódusait. Ezen módszerek némelyike statikus függvény lehet. A program összeállítása létrehoz egy szerelvény nevű fájlt, amely tartalmazza a lefordított kódot a közös köztes nyelven (CIL), és egy jegyzékfájlt, amely a függő szerelvényekre mutató összes hivatkozást tartalmazza.

Jegyzet

A szerelvények a CLR architektúrájának alapvető elemei. Ezek az alkalmazáskód csomagolásának, üzembe helyezésének és verziószámozásának egységei a .NET-keretrendszerben. A szerelvények használatával alkalmazáskódot helyezhet üzembe az adatbázisban, és egységes módot biztosít a teljes adatbázis-alkalmazások felügyeletére, biztonsági mentésére és visszaállítására.

A szerelvényjegyzék metaadatokat tartalmaz a szerelvényről, amely leírja a programban definiált összes struktúrát, mezőt, tulajdonságot, osztályt, öröklési kapcsolatokat, függvényeket és metódusokat. A jegyzék létrehozza a szerelvény identitását, megadja a szerelvény implementációját alkotó fájlokat, megadja a szerelvényt alkotó típusokat és erőforrásokat, részletezi a fordítási idő függőségeit más szerelvényeken, és megadja a szerelvény megfelelő futtatásához szükséges engedélyeket. Ezek az információk futásidőben használhatók a hivatkozások feloldásához, a verziókötési szabályzat kényszerítéséhez és a betöltött szerelvények integritásának ellenőrzéséhez.

A .NET-keretrendszer az osztályok, tulajdonságok, függvények és metódusok megjegyzéseinek egyéni attribútumait támogatja, az alkalmazás által metaadatokban rögzíthető további információkkal. Minden .NET-keretrendszer-fordító értelmezés nélkül használja ezeket a széljegyzeteket, és szerelvény-metaadatokként tárolja őket. Ezek a széljegyzetek ugyanúgy vizsgálhatók, mint bármely más metaadat.

A felügyelt kód végrehajtása a CLR-ben történik, nem pedig közvetlenül az operációs rendszer által. A felügyelt kódalkalmazások CLR-szolgáltatásokat szereznek be, például automatikus szemétgyűjtést, futásidejű típusellenőrzést és biztonsági támogatást. Ezek a szolgáltatások segítenek a felügyelt kódalkalmazások egységes platform- és nyelvfüggetlen viselkedésében.

A CLR-integráció tervezési céljai

Amikor a felhasználói kód a CLR által üzemeltetett környezetben fut az SQL Serverben (az úgynevezett CLR-integrációban), a következő tervezési célok érvényesek:

Megbízhatóság (biztonság)

A felhasználói kód nem hajthat végre olyan műveleteket, amelyek veszélyeztetik az adatbázismotor-folyamat integritását, például egy üzenetmezőt, amely felhasználói választ kér, vagy kilép a folyamatból. A felhasználói kód nem írhatja felül az adatbázismotor memóriapuffereit vagy belső adatstruktúráit.

Méretezhetőség

Az SQL Server és a CLR különböző belső modellekkel rendelkezik az ütemezéshez és a memóriakezeléshez. Az SQL Server támogatja a kooperatív, nem megelőző szálmodellt, amelyben a szálak önkéntesen, rendszeresen hajtanak végre végrehajtást, vagy amikor zárolásokra vagy I/O-ra várnak. A CLR támogatja a preemptive threading modellt. Ha az SQL Serveren futó felhasználói kód közvetlenül meghívja az operációs rendszer szálkezelésének primitíveit, akkor nem integrálható jól az SQL Server feladatütemezőbe, és csökkentheti a rendszer méretezhetőségét. A CLR nem tesz különbséget a virtuális és a fizikai memória között, de az SQL Server közvetlenül kezeli a fizikai memóriát, és konfigurálható korláton belül fizikai memóriát kell használnia.

A szálkezelés, az ütemezés és a memóriakezelés különböző modelljei integrációs kihívást jelentenek egy relációs adatbázis-kezelő rendszer (RDBMS) számára, amely több ezer egyidejű felhasználói munkamenetet támogat. Az architektúrának biztosítania kell, hogy a rendszer méretezhetőségét ne veszélyeztesse a felhasználói kód, amely közvetlenül meghívja az alkalmazásprogramozási felületeket (API-kat) a szálkezeléshez, a memóriához és a szinkronizálási primitívekhez.

Biztonság

Az adatbázisban futó felhasználói kódnak az SQL Server hitelesítési és engedélyezési szabályait kell követnie az adatbázis-objektumok, például táblák és oszlopok elérésekor. Emellett az adatbázisgazdáknak képesnek kell lenniük szabályozni az operációs rendszer erőforrásaihoz, például a fájlokhoz és a hálózati hozzáféréshez való hozzáférést az adatbázisban futó felhasználói kódból. Ez a gyakorlat fontossá válik, mivel a felügyelt programozási nyelvek (ellentétben a nem felügyelt nyelvekkel, például a Transact-SQL) api-kat biztosítanak az ilyen erőforrások eléréséhez. A rendszernek biztonságos módot kell biztosítania a felhasználói kód számára, hogy hozzáférjen a gép erőforrásaihoz az adatbázismotor folyamatán kívül. További információ: CLR integrációs biztonsági.

Teljesítmény

Az adatbázismotorban futó felügyelt felhasználói kód számítási teljesítményének hasonlónak kell lennie, mint a kiszolgálón kívül futtatott azonos kódnak. A felügyelt felhasználói kódból származó adatbázis-hozzáférés nem olyan gyors, mint a natív Transact-SQL. További információ: CLR integrációs architektúra teljesítménye.

CLR-szolgáltatások

A CLR számos szolgáltatást biztosít az SQL Serverrel való CLR-integráció tervezési céljainak eléréséhez.

Típusbiztonsági ellenőrzés

A típusbiztos kód olyan kód, amely csak jól meghatározott módon fér hozzá a memóriastruktúrákhoz. Érvényes objektumhivatkozás esetén például a típusbiztos kód a tényleges mezőtagoknak megfelelő rögzített eltolások esetén is hozzáférhet a memóriához. Ha azonban a kód tetszőleges eltolással fér hozzá a memóriához az objektumhoz tartozó memóriatartományon belül vagy kívül, akkor az nem típusbiztos. Amikor a szerelvények betöltődnek a CLR-be, a CIL igény szerinti fordítással történő fordítása előtt a futtatókörnyezet egy ellenőrzési fázist hajt végre, amely megvizsgálja a kódot a típusbiztonság meghatározásához. Az ellenőrzést sikeresen áttűnő kódot hitelesen típusbiztos kódnak nevezzük.

Alkalmazástartományok

A CLR támogatja az alkalmazástartományok végrehajtási zónáként való fogalmát egy gazdagépfolyamaton belül, ahol a felügyelt kódszerelvények betölthetők és végrehajthatók. Az alkalmazástartomány határa elkülöníti a szerelvényeket. A szerelvények a statikus változók és az adattagok láthatósága, valamint a kód dinamikus meghívásának képessége szempontjából vannak elkülönítve. Az alkalmazástartományok a kód be- és kirakodásának mechanizmusát is képezik. A kód csak az alkalmazástartomány kiürítésével távolítható el a memóriából. További információ: application domains and CLR Integration Security.

Kódhozzáférés biztonsága (CAS)

A CLR biztonsági rendszer lehetővé teszi annak szabályozását, hogy a felügyelt kód milyen típusú műveleteket hajthat végre az engedélyek kódhoz rendelésével. A kódhozzáférési engedélyek a kód identitása (például a szerelvény aláírása vagy a kód eredete) alapján vannak hozzárendelve.

A CLR egy számítógépszintű házirendet biztosít, amelyet a számítógép rendszergazdája állíthat be. Ez a szabályzat határozza meg a számítógépen futó felügyelt kódok engedély-megadását. Emellett van egy gazdagépszintű biztonsági szabályzat is, amelyet az olyan gazdagépek használhatnak, mint az SQL Server, hogy további korlátozásokat szabjanak meg a felügyelt kódra.

Ha a .NET-keretrendszer egyik felügyelt API-ja kódhozzáférési engedéllyel védett erőforrásokon teszi elérhetővé a műveleteket, az API ezt az engedélyt igényli az erőforrás elérése előtt. Ez az igény miatt a CLR biztonsági rendszere a hívásverem minden kódegységének (szerelvényének) átfogó ellenőrzését aktiválja. Az erőforrás csak akkor érhető el, ha a teljes híváslánc rendelkezik engedéllyel.

A felügyelt kód dinamikus generálásának képessége az Reflection.Emit API használatával nem támogatott az SQL Server CLR által üzemeltetett környezetében. Az ilyen kód nem rendelkezik cas-engedélyekkel a futtatáshoz, ezért futás közben meghiúsulna. További információ: CLR integrációs kódelérési biztonsági.

Gazdagépvédelmi attribútumok (HPA-k)

A CLR olyan mechanizmust biztosít, amely a .NET-keretrendszer részét képező felügyelt API-kat olyan attribútumokkal jegyzeteli, amelyek a CLR egy gazdagépe számára érdekesek lehetnek. Ilyen attribútumok például a következők:

  • SharedState, amely azt jelzi, hogy az API lehetővé teszi-e a megosztott állapot létrehozását vagy kezelését (például statikus osztálymezők).

  • Synchronization, amely azt jelzi, hogy az API lehetővé teszi-e a szálak közötti szinkronizálást.

  • ExternalProcessMgmt, amely azt jelzi, hogy az API elérhetővé teszi-e a gazdafolyamat szabályozásának módját.

Ezen attribútumok figyelembe adásával a gazdagép megadhatja a hpa-k listáját, például a SharedState attribútumot, amelyeket a üzemeltetett környezetben el kell tiltani. Ebben az esetben a CLR tagadja, hogy felhasználói kóddal kísérelné meg meghívni azokat az API-kat, amelyeket a HPA-k a tiltott listában jegyzetelnek. További információ: Gazdagépvédelmi attribútumok és CLR integrációs programozás.

Az SQL Server és a CLR együttműködése

Ez a szakasz azt ismerteti, hogy az SQL Server hogyan integrálja az SQL Server és a CLR szálkezelési, ütemezési, szinkronizálási és memóriakezelési modelljeit. Ez a szakasz különösen a méretezhetőség, a megbízhatóság és a biztonsági célok fényében vizsgálja az integrációt. Az SQL Server lényegében operációs rendszerként működik a CLR-hez, amikor az SQL Serveren belül van üzemeltetve. A CLR alacsony szintű rutinokat hív meg az SQL Server által a szálkezelés, az ütemezés, a szinkronizálás és a memóriakezelés céljából. Ezek a rutinok ugyanazok a primitívek, mint az SQL Server többi motorja. Ez a megközelítés számos skálázhatósági, megbízhatósági és biztonsági előnyt biztosít.

Méretezhetőség: Gyakori szálkezelés, ütemezés és szinkronizálás

A CLR meghívja az SQL Server API-kat a szálak létrehozásához, mind a felhasználói kód futtatásához, mind a saját belső használatához. Több szál közötti szinkronizáláshoz a CLR meghívja az SQL Server szinkronizálási objektumait. Ez a gyakorlat lehetővé teszi, hogy az SQL Server ütemezője más feladatokat ütemezzen, amikor egy szál egy szinkronizálási objektumra vár. Ha például a CLR kezdeményezi a szemétgyűjtést, az összes szála megvárja, amíg a szemétgyűjtés befejeződik. Mivel a CLR-szálakat és az általuk várt szinkronizálási objektumokat az SQL Server ütemezője ismeri, az SQL Server ütemezheti azokat a szálakat, amelyek más, a CLR-t nem érintő adatbázis-feladatokat futtatnak. Ez lehetővé teszi továbbá, hogy az SQL Server észlelje azokat a holtpontokat, amelyek a CLR-szinkronizálási objektumok által végrehajtott zárolásokat foglalják magukban, és hagyományos technikákat alkalmaznak a holtpont eltávolítására.

A felügyelt kód előre fut az SQL Serveren. Az SQL Server ütemezője képes észlelni és leállítani azokat a szálakat, amelyek jelentős ideje nem engedett. A CLR-szálak SQL Server-szálakhoz való kapcsolásának képessége azt jelenti, hogy az SQL Server ütemezője képes azonosítani a "futtató" szálakat a CLR-ben, és kezelni a prioritásukat. Az ilyen elszabadult szálak fel vannak függesztve, és vissza lesznek helyezve az üzenetsorba. Az ismétlődően elfutott szálakként azonosított szálak nem futtathatók egy adott ideig, hogy más végrehajtó feldolgozók is fussanak.

Vannak olyan helyzetek, amikor a hosszú ideig futó felügyelt kód automatikusan hozamot eredményez, és vannak olyan helyzetek, amikor nem. A következő helyzetekben a hosszú ideig futó felügyelt kód automatikusan hozamot eredményez:

  • Ha a kód meghívja az SQL OS-t (például adatok lekérdezéséhez)
  • Ha elegendő memória van lefoglalva a szemétgyűjtés aktiválásához
  • Ha a kód operációsrendszer-függvények meghívásával preemptív módot ad meg

Azok a kódok, amelyek nem hajtanak végre ezen műveletek egyikét sem, például a csak számítást tartalmazó szoros hurkok, nem eredményezik automatikusan az ütemezőt, ami hosszú várakozást eredményezhet a rendszer többi számítási feladatára. Ezekben az esetekben a fejlesztőnek kell explicit módon hozamot eredményeznie a .NET-keretrendszer System.Thread.Sleep() függvényének meghívásával, vagy a preemptív mód System.Thread.BeginThreadAffinity()használatával történő kifejezett beírásával a kód minden olyan szakaszában, amely várhatóan hosszú ideig fut. Az alábbi példakódok bemutatják, hogyan lehet manuálisan hozamot adni az egyes metódusok használatával.

Példák

Manuális hozam az SOS-ütemezőnek

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);
  }
}

A ThreadAffinity használata előzetes futtatáshoz

Ebben a példában a CLR-kód megelőző módban fut BeginThreadAffinity és 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();

Méretezhetőség: Gyakori memóriakezelés

A CLR meghívja az SQL Server primitíveit a memória felszabadítására és felszabadítására. Mivel a CLR által használt memória a rendszer teljes memóriahasználatában van elszámolva, az SQL Server a konfigurált memóriakorláton belül maradhat, és biztosíthatja, hogy a CLR és az SQL Server ne versengenek egymással a memóriaért. Az SQL Server akkor is elutasíthatja a CLR-memóriakéréseket, ha a rendszermemória korlátozott, és megkérheti a CLR-t, hogy csökkentse a memóriahasználatot, ha más feladatoknak memóriára van szükségük.

Megbízhatóság: Alkalmazástartományok és helyreállíthatatlan kivételek

Ha a .NET-keretrendszer API-jaiban felügyelt kód kritikus kivételekkel találkozik, például a memóriakimaradás vagy a verem túlcsordulása, nem mindig lehet helyreállítani ezeket a hibákat, és konzisztens és helyes szemantikát biztosítani a megvalósításukhoz. Ezek az API-k a hibákra válaszul megszakítják a szálak kivételét.

Az SQL Serveren üzemeltetett ilyen szálleborulások kezelése a következőképpen történik: a CLR észleli a megosztott állapotokat abban az alkalmazástartományban, amelyben a szál megszakad. A CLR ezt a szinkronizálási objektumok jelenlétének ellenőrzésével észleli. Ha az alkalmazástartományban megosztott állapot található, akkor maga az alkalmazástartomány is ki van ürítve. Az alkalmazástartomány kiürítése leállítja az adott alkalmazástartományban jelenleg futó adatbázis-tranzakciókat. Mivel a megosztott állapot jelenléte az ilyen kritikus kivételek hatását a kivételt kiváltótól eltérő felhasználói munkamenetekre is ki tudja terjeszteni, az SQL Server és a CLR lépéseket tett a megosztott állapot valószínűségének csökkentése érdekében. További információ: .NET-keretrendszer.

Biztonság: Engedélykészletek

Az SQL Server lehetővé teszi, hogy a felhasználók megadják az adatbázisban üzembe helyezett kód megbízhatósági és biztonsági követelményeit. Amikor szerelvényeket tölt fel az adatbázisba, a szerelvény szerzője megadhat egy három engedélykészletet az adott szerelvényhez: SAFE, EXTERNAL_ACCESSés UNSAFE.

Funkcionalitás SAFE EXTERNAL_ACCESS UNSAFE
Code Access Security Csak végrehajtás Végrehajtás + hozzáférés külső erőforrásokhoz Korlátlan
Programming model restrictions Igen Igen Nincsenek korlátozások
Verifiability requirement Igen Igen Nem
Ability to call native code Nem Nem Igen

SAFE a legmegbízhatóbb és legbiztonságosabb mód az engedélyezett programozási modellre vonatkozó korlátozásokkal. SAFE szerelvények elegendő engedélyt kapnak a futtatáshoz, a számítások elvégzéséhez és a helyi adatbázishoz való hozzáféréshez. SAFE szerelvényeknek ellenőrizhetően biztonságosnak kell lenniük, és nem hívhatnak nem felügyelt kódot.

UNSAFE olyan megbízható kódhoz készült, amelyet csak adatbázis-rendszergazdák hozhatnak létre. Ez a megbízható kód nem rendelkezik kódhozzáférés biztonsági korlátozásokkal, és meghívhat nem felügyelt (natív) kódot.

EXTERNAL_ACCESS köztes biztonsági lehetőséget biztosít, amely lehetővé teszi, hogy a kód hozzáférjen az adatbázison kívüli erőforrásokhoz, de továbbra is rendelkezik a SAFEmegbízhatósági garanciáival.

Az SQL Server a gazdagépszintű CAS-szabályzatréteggel állít be egy gazdagépházirendet, amely az SQL Server-katalógusokban tárolt engedélykészlet alapján megadja a három engedélycsoport egyikét. Az adatbázisban futó felügyelt kód mindig megkapja az ilyen kódhozzáférés-engedélykészletek egyikét.

Programozási modell korlátozásai

Az SQL Server felügyelt kódjának programozási modellje olyan függvények, eljárások és típusok írását foglalja magában, amelyek általában nem igénylik a több meghívásban vagy az állapot több felhasználói munkamenetben való megosztását. A korábban leírtaknak megfelelően a megosztott állapot jelenléte kritikus kivételeket okozhat, amelyek befolyásolják az alkalmazás méretezhetőségét és megbízhatóságát.

Ezeket a szempontokat figyelembe véve nem javasoljuk az SQL Serverben használt osztályok statikus változóinak és statikus adattagjainak használatát. SAFE és EXTERNAL_ACCESS szerelvények esetében az SQL Server CREATE ASSEMBLY időpontban megvizsgálja a szerelvény metaadatait, és nem hozza létre az ilyen szerelvényeket, ha statikus adattagok és változók használatát találja.

Az SQL Server emellett letiltja azokat a .NET-keretrendszer API-kat, amelyek a SharedState, Synchronizationés ExternalProcessMgmt gazdagépvédelmi attribútumokkal vannak jegyzetelve. Ez megakadályozza, hogy SAFE és EXTERNAL_ACCESS szerelvények meghívják azokat az API-kat, amelyek engedélyezik a megosztási állapotot, szinkronizálást hajtanak végre, és befolyásolják az SQL Server-folyamat integritását. További információ: CLR integrációs modell korlátozásai.