Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A következőkre vonatkozik:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Analytics Platform System (PDW)
SQL Database a Microsoft Fabric
Bármely adatbázisban a tranzakciók helytelen kezelése gyakran versengéshez és teljesítményproblémákhoz vezet a sok felhasználóval rendelkező rendszerekben. Az adatokhoz hozzáférő felhasználók számának növekedésével fontossá válik, hogy a tranzakciókat hatékonyan használó alkalmazások is működjenek. Ez az útmutató az adatbázismotor által az egyes tranzakciók integritásának biztosításához használt zárolási és sor-verziószámozási mechanizmusokat ismerteti, és tájékoztatást nyújt arról, hogy az alkalmazások hogyan szabályozhatják hatékonyan a tranzakciókat.
Jegyzet
Optimalizált zárolási egy 2023-ban bevezetett adatbázismotor-funkció, amely drasztikusan csökkenti a zárolási memóriát és az egyidejű írásokhoz szükséges zárolások számát. Ez a cikk úgy frissül, hogy leírja az adatbázismotor működését optimalizált zárolással és anélkül.
- További információkért és az optimalizált zárolás elérhetőségének megismeréséhez tekintse meg optimalizált zárolásicímű témakört.
- Annak megállapításához, hogy az optimalizált zárolás engedélyezve van-e az adatbázisban, olvassa el Engedélyezve van-e az optimalizált zárolás?
Az optimalizált zárolás jelentős változásokat vezet be a cikk egyes szakaszaiban, például:
A tranzakció alapjai
A tranzakció a műveletek sorozata, amelyet egyetlen logikai egységként hajtanak végre. A logikai munkaegységnek négy tulajdonságot kell tartalmaznia, az atomitást, konzisztenciát, elkülönítést és tartóssági (ACID) tulajdonságokat, hogy tranzakciónak minősüljenek.
Atomicitás
A tranzakciónak atomi munkaegységnek kell lennie; vagy az összes adatmódosítást végrehajtják, vagy egyik sem történik meg.
Következetesség
Ha befejeződött, a tranzakciónak konzisztens állapotban kell hagynia az összes adatot. Egy relációs adatbázisban minden szabályt alkalmazni kell a tranzakció módosításaira az összes adatintegritás fenntartása érdekében. A tranzakció végén minden belső adatstruktúrának, például a B-fa indexeinek vagy a duplázott listáknak helyesnek kell lenniük.
Jegyzet
A dokumentáció általában a B-fa kifejezést használja az indexekre hivatkozva. A sorkataszterekben az adatbázismotor egy B+ fát implementál. Ez nem vonatkozik az oszlopcentrikus indexekre vagy a memóriaoptimalizált táblák indexére. További információ: SQL Server és Azure SQL index architektúrája és tervezési útmutatója.
elkülönítés
Az egyidejű tranzakciók által végrehajtott módosításokat el kell különíteni a többi egyidejű tranzakció módosításaitól. A tranzakciók vagy abban az állapotban ismerik fel az adatokat, amelyben egy másik egyidejű tranzakció módosította azokat, vagy felismeri az adatokat a második tranzakció befejezése után, de nem ismer fel köztes állapotot. Ezt szerializálhatóságnak nevezzük, mivel lehetővé teszi a kiindulási adatok újratöltését és egy tranzakciósorozat újrajátszását, hogy az adatok ugyanabban az állapotban legyenek, mint az eredeti tranzakciók végrehajtása után.
tartósság
A teljes mértékben tartós tranzakció befejeződése után annak hatásai véglegesen érvényesülnek a rendszerben. A módosítások rendszerhiba esetén is megmaradnak. Az SQL Server 2014 (12.x) és újabb verziói késleltetett tartós tranzakciókat tesznek lehetővé. A késleltetett tartós tranzakciók véglegesítése még azelőtt történik, hogy a tranzakciónapló bejegyzése tartósan a lemezre íródna. A tranzakciók késleltetett tartósságáról további információt a Tranzakció tartósságának szabályozásacímű cikkben talál.
Az alkalmazások felelősek a tranzakciók elindításáért és befejezéséért olyan pontokon, amelyek kikényszeríti az adatok logikai konzisztenciáját. Az alkalmazásnak meg kell határoznia az adatmódosítások sorozatát, amelyek konzisztens állapotban hagyják az adatokat a szervezet üzleti szabályaihoz képest. Az alkalmazás egyetlen tranzakcióban hajtja végre ezeket a módosításokat, hogy az adatbázismotor érvényesíthesse a tranzakció integritását.
Egy vállalati adatbázisrendszer, például az adatbázismotor egy példányának felelőssége, hogy olyan mechanizmusokat biztosítson, amelyek biztosítják az egyes tranzakciók integritását. Az adatbázismotor a következő lehetőségeket biztosítja:
A tranzakcióelkülönítést megőrző zárolási létesítmények.
Naplózási létesítmények a tranzakciók tartósságának biztosítása érdekében. A teljes mértékben tartós tranzakciók esetében a naplórekordot a rendszer a tranzakciók véglegesítése előtt lemezre edzi. Így még ha a kiszolgáló hardvere, operációs rendszere vagy maga az adatbázismotor példánya is meghibásodik, a példány az újraindításkor a tranzakciónaplókkal automatikusan visszaállítja a hiányos tranzakciókat a rendszerhiba pontjára. A késleltetett tartós tranzakciók még azelőtt véglegesítődnek, hogy a tranzakciónaplóban szereplő rekordok lemezre kerülnének. Az ilyen tranzakciók elveszhetnek, ha rendszerhiba lép fel a naplórekord lemezre való rögzítése előtt. A tranzakciók késleltetett tartósságáról további információt a Tranzakció tartósságának szabályozásacímű cikkben talál.
Tranzakciókezelési funkciók, amelyek a tranzakció atomitását és konzisztenciáját kényszerítik ki. A tranzakció elindítása után sikeresnek (véglegesítettnek) kell lennie, vagy az adatbázismotor visszavonja a tranzakció által a tranzakció elindítása óta végrehajtott összes adatmódosítást. Ezt a műveletet tranzakció visszagördülésének nevezzük, mert az adatokat a módosítások előtti állapotba adja vissza.
Tranzakciók szabályozása
Az alkalmazások elsősorban a tranzakciókat szabályozzák, ha megadják, hogy mikor kezdődnek és fejeződnek be a tranzakciók. Ez Transact-SQL utasítások vagy adatbázis-alkalmazásprogramozási felület (API) függvények használatával adható meg. A rendszernek képesnek kell lennie arra is, hogy megfelelően kezelje a tranzakciók befejezését megelőző hibákat. További információért lásd: Tranzakciók, Tranzakciók végrehajtása ODBC-ben, és Tranzakciók az SQL Server Native Clientben.
Alapértelmezés szerint a tranzakciók a kapcsolat szintjén vannak kezelve. Amikor egy tranzakció egy kapcsolaton indul el, az adott kapcsolaton végrehajtott összes Transact-SQL utasítás a tranzakció részét képezi, amíg a tranzakció véget nem ér. Több aktív eredményhalmaz (MARS) munkamenetben azonban egy Transact-SQL explicit vagy implicit tranzakció kötegalapú tranzakcióvá válik, amelyet a köteg szintjén kezelnek. Ha a köteg befejeződik, a köteg hatókörű tranzakció véglegesítése vagy visszagördítése nem történik meg, az adatbázismotor automatikusan visszaállítja azt. További információért lásd: Több aktív eredményhalmaz (MARS).
Tranzakciók indítása
API-függvények és Transact-SQL utasítások használatával explicit, automatikus vagy implicit tranzakciókként indíthat tranzakciókat.
Explicit tranzakciók
Az explicit tranzakció olyan, amelyben explicit módon definiálja a tranzakció kezdetét és végét egy API-függvényen keresztül, vagy a Transact-SQL BEGIN TRANSACTION
, COMMIT TRANSACTION
, COMMIT WORK
, ROLLBACK TRANSACTION
vagy ROLLBACK WORK
Transact-SQL utasítások kiadásával. Amikor a tranzakció véget ér, a kapcsolat visszaáll arra a tranzakciós módra, amelyben a explicit tranzakció elindítása előtt volt, ami lehet implicit vagy automatikus válasz mód.
Az összes Transact-SQL utasítást használhatja egy explicit tranzakcióban, kivéve a következő utasításokat:
CREATE DATABASE
ALTER DATABASE
DROP DATABASE
CREATE FULLTEXT CATALOG
ALTER FULLTEXT CATALOG
DROP FULLTEXT CATALOG
DROP FULLTEXT INDEX
ALTER FULLTEXT INDEX
CREATE FULLTEXT INDEX
BACKUP
RESTORE
RECONFIGURE
- Teljes szöveges rendszer tárolt eljárásai
-
sp_dboption
az adatbázis beállításainak vagy azmaster
adatbázist explicit vagy implicit tranzakciókon belül módosító rendszereljárások beállítására.
Jegyzet
UPDATE STATISTICS
explicit tranzakción belül is használható. Azonban a UPDATE STATISTICS
a környező tranzakciótól függetlenül véglegesül, és nem vonható vissza.
automatikus kiírási tranzakciók
Az automatikus feladatátvételi mód az adatbázismotor alapértelmezett tranzakciókezelési módja. Minden Transact-SQL utasítás véglegesítése vagy visszaállítása a befejezéskor történik. Ha egy utasítás sikeresen befejeződött, az véglegesítésre kerül; ha bármilyen hibába ütközik, az vissza lesz állítva. Az adatbázismotor egy példányával való kapcsolat automatikus kapcsolódási módban működik, ha ezt az alapértelmezett módot nem bírálták felül explicit vagy implicit tranzakciók. Az automatikus kitöltési mód az SqlClient, az ADO, az OLE DB és az ODBC alapértelmezett módja is.
implicit tranzakciók
Ha egy kapcsolat implicit tranzakciós módban működik, az adatbázismotor példánya automatikusan elindít egy új tranzakciót az aktuális tranzakció véglegesítése vagy visszaállítása után. Semmit sem tesz a tranzakció kezdetének lehatárlásához; csak az egyes tranzakciók véglegesítését vagy visszaállítását hajtja végre. Az implicit tranzakciós mód a tranzakciók folyamatos láncát hozza létre. Implicit tranzakciós mód beállítása API-függvényen vagy Transact-SQL SET IMPLICIT_TRANSACTIONS ON
utasításon keresztül. Ezt a módot automatikus kikapcsolásnak is nevezik, lásd setAutoCommit metódus (SQLServerConnection).
Miután az implicit tranzakciós mód engedélyezve van egy kapcsolathoz, az adatbázismotor példánya automatikusan elindít egy tranzakciót, amikor először végrehajtja az alábbi utasítások bármelyikét:
ALTER TABLE
CREATE
DELETE
DENY
DROP
FETCH
GRANT
INSERT
OPEN
REVOKE
SELECT
TRUNCATE
UPDATE
Csoport-hatókörű tranzakciók
Csak kizárólag több aktív eredményhalmazra (MARS) alkalmazható, bármely, a MARS-munkamenetben elindított Transact-SQL explicit vagy implicit tranzakció a munkamenetre korlátozott hatókörű tranzakcióvá válik. Az adatbázismotor automatikusan visszagörget minden köteg hatókörű tranzakciót, amelyet a köteg befejezésekor nem véglegesítettek vagy nem gördítettek vissza.
elosztott tranzakciók
Az elosztott tranzakciók két vagy több, erőforrás-kezelőként ismert kiszolgálóra terjednek ki. A tranzakció kezelését az erőforrás-kezelők között egy tranzakciókezelő nevű kiszolgálói összetevőnek kell koordinálnia. Az adatbázismotor minden példánya erőforrás-kezelőként működhet a tranzakciókezelők által koordinált elosztott tranzakciókban, például a Microsoft Elosztott tranzakció koordinátora (MS DTC) vagy más tranzakciókezelőkben, amelyek támogatják az elosztott tranzakciók feldolgozására vonatkozó open group XA specifikációt. További információkért tekintse meg az MS DTC dokumentációját.
A két vagy több adatbázist felölelő adatbázismotor egyetlen példányán belüli tranzakció elosztott tranzakció. A példány belsőleg kezeli az elosztott tranzakciót; a felhasználó számára helyi tranzakcióként működik.
Az alkalmazásban az elosztott tranzakciók kezelése ugyanúgy történik, mint egy helyi tranzakció. A tranzakció végén az alkalmazás azt kéri, hogy a tranzakciót vagy véglegesítsék, vagy gördítsék vissza. Az elosztott véglegesítéseket a tranzakciókezelőnek másképpen kell kezelnie, hogy minimálisra csökkentse annak kockázatát, hogy egy hálózati hiba miatt egyes erőforrás-kezelők sikeresen véglegesítik a tranzakciót, míg mások visszaállítják a tranzakciót. Ez úgy érhető el, hogy a véglegesítési folyamatot két fázisban (a előkészítési fázisban és a véglegesítési fázisban) kezeli, amelyet kétfázisú véglegesítésnek nevezünk.
fázis előkészítése
Amikor a tranzakciókezelő véglegesítési kérelmet kap, egy előkészítési parancsot küld a tranzakcióban részt vevő összes erőforrás-kezelőnek. Ezután minden erőforrás-kezelő megtesz mindent, ami a tranzakció tartóssá tételéhez szükséges, és a tranzakció összes tranzakciónapló-puffere kiíródik a lemezre. Mivel minden erőforrás-kezelő befejezi az előkészítési fázist, a tranzakciókezelőnek visszaadja a fázis sikerességét vagy sikertelenségét. Az SQL Server 2014 (12.x) késleltetett tranzakciós tartósságot vezetett be. A késleltetett tartós tranzakciók véglegesítése azelőtt történik, hogy az egyes erőforrás-kezelők tranzakciónapló-pufferei kiürülnének a lemezre. A tranzakciók késleltetett tartósságáról további információt a Tranzakció tartósságának szabályozásacímű cikkben talál.
véglegesítési fázis
Ha a tranzakciókezelő sikeres előkészületeket kap az összes erőforrás-kezelőtől, véglegesítési parancsokat küld az egyes erőforrás-kezelőknek. Az erőforrás-kezelők ezután befejezhetik a véglegesítést. Ha az összes erőforrás-kezelő sikeres véglegesítésről számol be, a tranzakciókezelő sikeres értesítést küld az alkalmazásnak. Ha valamelyik erőforrás-kezelő sikertelen előkészítési hibát jelentett, a tranzakciókezelő egy visszaállítási parancsot küld az egyes erőforrás-kezelőknek, és jelzi az alkalmazás véglegesítésének sikertelenségét.
Az adatbázismotor-alkalmazások az elosztott tranzakciókat Transact-SQL vagy az adatbázis API-val kezelhetik. További információ: BEGIN DISTRIBUTED TRANSACTION (Transact-SQL).
Tranzakciók lezárása
A tranzakciókat véglegesítési vagy ROLLBACK utasítással, vagy egy megfelelő API-függvény használatával is befejezheti.
Követés
Ha egy tranzakció sikeres, véglegesítse. A
COMMIT
utasítás garantálja, hogy a tranzakció összes módosítása az adatbázis állandó részét képezi. A véglegesítés a tranzakció által használt erőforrásokat, például zárolásokat is felszabadítja.Visszavonás
Ha hiba történik egy tranzakcióban, vagy ha a felhasználó úgy dönt, hogy megszakítja a tranzakciót, hajtsa vissza a tranzakciót. A
ROLLBACK
utasítás a tranzakcióban végrehajtott összes módosítást visszavonja úgy, hogy visszaadja az adatokat a tranzakció elején megadott állapotba. A visszaállítás a tranzakció által birtokolt erőforrásokat is felszabadítja.
Jegyzet
Több aktív eredményhalmaz (MARS) munkamenet esetén az API-függvényen keresztül indított explicit tranzakció nem véglegesíthető, amíg végrehajtási kérelmek vannak függőben. Ha ilyen típusú tranzakciót kísérel meg véglegesíteni a kérések végrehajtása közben, az hibát eredményez.
Tranzakciók feldolgozása során előforduló hibák
Ha egy hiba megakadályozza egy tranzakció sikeres befejezését, az adatbázismotor automatikusan visszaállítja a tranzakciót, és felszabadítja a tranzakció által birtokolt összes erőforrást. Ha megszakad az ügyfél hálózati kapcsolata az Adatbázismotor egy példányával, a rendszer visszagörgeti a kapcsolathoz tartozó minden függőben lévő tranzakciót, amikor a hálózat értesíti a példányt a kapcsolattörésről. Ha az ügyfélalkalmazás meghibásodik, vagy ha az ügyfélszámítógép leáll vagy újraindul, az is megszakítja a kapcsolatot, és az adatbázismotor példánya visszaállítja a fennálló tranzakciókat, amikor a hálózat értesíti a kapcsolat megszakadásáról. Ha az ügyfél megszakítja a kapcsolatot az adatbázismotorral, a rendszer visszaállítja a folyamatban lévő tranzakciókat.
Ha futásidejű utasításhiba (például kényszer megsértése) történik egy kötegben, az adatbázismotor alapértelmezett viselkedése csak a hibát létrehozó utasítás visszaállítása. Ezt a viselkedést a SET XACT_ABORT ON
utasítással módosíthatja. A SET XACT_ABORT ON
végrehajtása után minden futásidejű utasításhiba az aktuális tranzakció automatikus visszaállítását eredményezi. A fordítási hibákat( például szintaxishibákat) a SET XACT_ABORT
nem érinti. További információért lásd: SET XACT_ABORT (Transact-SQL).
Hibák esetén a megfelelő műveletet (COMMIT
vagy ROLLBACK
) bele kell foglalni az alkalmazáskódba. Az egyik hatékony eszköz a hibák kezelésére, beleértve a tranzakciókat is, a Transact-SQL TRY...CATCH
szerkezet. További információk a tranzakciókat tartalmazó példákkal kapcsolatban: TRY... CATCH (Transact-SQL). Az SQL Server 2012 -től (11.x) kezdődően a THROW
utasítással kivételt emelhet ki, és átviheti a végrehajtást egy CATCH
szerkezet TRY...CATCH
blokkjába. További információ: THROW (Transact-SQL).
Fordítási és futásidejű hibák automatikus feladatátvételi módban
Automatikus kiegészítés módban néha úgy tűnik, mintha az adatbázismotor egy példánya egy teljes köteget gördített volna vissza egyetlen SQL-utasítás helyett. Ez akkor fordul elő, ha a hiba fordítási hiba, nem futásidejű hiba. Fordítási hiba megakadályozza, hogy az adatbázismotor végrehajtási tervet készítsen, ezért a kötegben semmi sem hajtható végre. Bár úgy tűnik, hogy a hibát okozó utasítást megelőző összes utasítás vissza lett vonva, a hiba megakadályozta a kötegben lévő összes művelet végrehajtását. Az alábbi példában a harmadik köteg egyik INSERT
utasítása sem lesz végrehajtva fordítási hiba miatt. Úgy tűnik, hogy az első két INSERT
utasítás visszaállításra kerül, mivel soha nem kerülnek végrehajtásra.
CREATE TABLE TestBatch (ColA INT PRIMARY KEY, ColB CHAR(3));
GO
INSERT INTO TestBatch VALUES (1, 'aaa');
INSERT INTO TestBatch VALUES (2, 'bbb');
INSERT INTO TestBatch VALUSE (3, 'ccc'); -- Syntax error.
GO
SELECT * FROM TestBatch; -- Returns no rows.
GO
Az alábbi példában a harmadik INSERT
utasítás futásidejű ismétlődő elsődlegeskulcs-hibát hoz létre. Az első két INSERT
utasítás sikeres és elfogadott, így a futásidejű hiba után is megmaradnak.
CREATE TABLE TestBatch (ColA INT PRIMARY KEY, ColB CHAR(3));
GO
INSERT INTO TestBatch VALUES (1, 'aaa');
INSERT INTO TestBatch VALUES (2, 'bbb');
INSERT INTO TestBatch VALUES (1, 'ccc'); -- Duplicate key error.
GO
SELECT * FROM TestBatch; -- Returns rows 1 and 2.
GO
Az adatbázismotor halasztott névfeloldást használ, ahol az objektumnevek feloldása a végrehajtáskor, nem a fordítási időpontban van. A következő példában az első két INSERT
utasítás végrehajtása és véglegesítése történik meg, és ez a két sor a TestBatch
táblában marad, miután a harmadik INSERT
utasítás futásidejű hibát okoz egy nem létező táblára hivatkozva.
CREATE TABLE TestBatch (ColA INT PRIMARY KEY, ColB CHAR(3));
GO
INSERT INTO TestBatch VALUES (1, 'aaa');
INSERT INTO TestBatch VALUES (2, 'bbb');
INSERT INTO TestBch VALUES (3, 'ccc'); -- Table name error.
GO
SELECT * FROM TestBatch; -- Returns rows 1 and 2.
GO
A zárolás és a sor verziószámozásának alapjai
Az adatbázismotor a következő mechanizmusokkal biztosítja a tranzakciók integritását, és fenntartja az adatbázisok konzisztenciáját, amikor több felhasználó egyszerre fér hozzá az adatokhoz:
Zárolás
Minden tranzakció különböző típusú zárolásokat kér azon erőforrásokon, például sorokon, oldalakon vagy táblákon, amelyektől a tranzakció függ. A zárolások megakadályozzák, hogy más tranzakciók úgy módosítsák az erőforrásokat, hogy az problémákat okozzon a zárolást kérő tranzakció esetében. Minden tranzakció felszabadítja a zárolásokat, ha már nincs függősége a zárolt erőforrásoktól.
Sorváltozatok kezelése
Ha sorverzióalapú elkülönítési szintet használ, az adatbázismotor fenntartja a módosított sorok verzióit. Az alkalmazások megadhatják, hogy egy tranzakció a sorverziókat használja az adatok megtekintésére úgy, ahogy azok a tranzakció vagy utasítás kezdetekor voltak, ahelyett, hogy az összes olvasáshoz zárolást használna a védelemhez. A sorverziók használatával jelentősen csökken annak az esélye, hogy egy olvasási művelet blokkolja a többi tranzakciót.
A zárolás és a sorverziózás megakadályozza, hogy a felhasználók olvassák a nem véglegesített adatokat, és megakadályozzák, hogy egyszerre több felhasználó is megkísérlje ugyanazon adatok módosítását. Zárolás vagy sorverzió nélkül az adatokon végrehajtott lekérdezések váratlan eredményeket eredményezhetnek az adatbázisban még nem véglegesített adatok visszaadásával.
Az alkalmazások kiválaszthatják a tranzakcióelkülönítési szinteket, amelyek meghatározzák a tranzakció védelmének szintjét más tranzakciók módosításával szemben. Táblázatszintű tippeket adhat meg az egyes Transact-SQL utasításokhoz, hogy a viselkedést az alkalmazás követelményeinek megfelelően alakítsa.
Egyidejű adathozzáférés kezelése
Azok a felhasználók, akik egyszerre férnek hozzá egy erőforráshoz, azt mondják, hogy egyidejűleg férnek hozzá az erőforráshoz. Az egyidejű adathozzáféréshez olyan mechanizmusokra van szükség, amelyek megakadályozzák a káros hatásokat, ha több felhasználó próbálja módosítani a más felhasználók által aktívan használt erőforrásokat.
Egyidejűségi effektusok
Az adatokat módosító felhasználók más felhasználókat is érinthetnek, akik egyszerre olvassák vagy módosítják ugyanazokat az adatokat. Ezek a felhasználók állítólag egyszerre férnek hozzá az adatokhoz. Ha egy adatbázis nem rendelkezik egyidejűségi vezérléssel, a felhasználók a következő mellékhatásokat láthatják:
Elveszett frissítések
Az elveszett frissítések akkor fordulnak elő, ha két vagy több tranzakció ugyanazt a sort választja ki, majd frissíti a sort az eredetileg kiválasztott érték alapján. Az egyes tranzakciók nem ismerik a többi tranzakciót. Az utolsó frissítés felülírja a többi tranzakció által végrehajtott frissítéseket, ami adatvesztést eredményez.
Két szerkesztő például elektronikus másolatot készít ugyanabból a dokumentumból. Minden szerkesztő egymástól függetlenül módosítja a másolatot, majd menti a módosított másolatot, és felülírja az eredeti dokumentumot. A módosított másolatot mentő szerkesztő felülírja a másik szerkesztő által végrehajtott módosításokat. Ez a probléma elkerülhető, ha az egyik szerkesztő nem fér hozzá a fájlhoz, amíg a másik szerkesztő nem fejezte be és nem véglegesítette a tranzakciót.
nem véglegesített függőség (piszkos olvasás)
A nem véglegesített függőség akkor fordul elő, ha egy második tranzakció egy másik tranzakció által frissített sort olvas be. A második tranzakció az adatok beolvasása, amelyeket még nem véglegesítettek, és amelyeket a sort frissítő tranzakció módosíthat.
Egy szerkesztő például módosít egy elektronikus dokumentumot. A módosítások során a második szerkesztő másolatot készít a dokumentumról, amely tartalmazza az eddig végrehajtott módosításokat, és elosztja a dokumentumot a kívánt közönségnek. Az első szerkesztő ezután úgy dönt, hogy az eddig végrehajtott módosítások helytelenek, és eltávolítja a módosításokat, és menti a dokumentumot. Az elosztott dokumentum olyan módosításokat tartalmaz, amelyek már nem léteznek, és úgy kell kezelni őket, mintha soha nem léteznének. Ez a probléma elkerülhető, ha senki sem tudja elolvasni a módosított dokumentumot, amíg az első szerkesztő nem menti a módosításokat, és véglegesíti a tranzakciót.
Inkonzisztens elemzés (nem megismételhető olvasás)
Inkonzisztens elemzés akkor fordul elő, ha egy második tranzakció többször is hozzáfér ugyanahhoz a sorhoz, és minden alkalommal különböző adatokat olvas be. Az inkonzisztens elemzés hasonló a nem véglegesített függőséghez, mert egy másik tranzakció módosítja a második tranzakció által beolvasott adatokat. Inkonzisztens elemzés esetén azonban a második tranzakció által beolvasott adatokat a módosítást okozó tranzakció véglegesítette. Az inkonzisztens elemzés magában foglalja ugyanahhoz a sorhoz tartozó több olvasást (kettő vagy több), és minden alkalommal, amikor az adatokat egy másik tranzakció módosítja; így a nem megismételhető olvasott kifejezés.
Egy szerkesztő például kétszer olvassa be ugyanazt a dokumentumot, de az egyes olvasások között az író újraírja a dokumentumot. Amikor a szerkesztő másodszor olvassa be a dokumentumot, az megváltozott. Az eredeti olvasás nem volt megismételhető. Ez a probléma elkerülhető, ha az író nem tudta módosítani a dokumentumot, amíg a szerkesztő nem olvassa el utoljára.
Phantom felolvassa
A fantomolvasás olyan helyzet, amely két azonos lekérdezés végrehajtásakor történik, és a második lekérdezés által visszaadott sorok halmaza eltérő. Az alábbi példa bemutatja, hogyan fordulhat elő ez. Tegyük fel, hogy a két tranzakció egyszerre fut. Az első tranzakcióban szereplő két
SELECT
utasítás eltérő eredményeket adhat vissza, mert a második tranzakcióINSERT
utasítása megváltoztatja a két tranzakció által használt adatokat.--Transaction 1 BEGIN TRAN; SELECT ID FROM dbo.employee WHERE ID > 5 AND ID < 10; --The INSERT statement from the second transaction occurs here. SELECT ID FROM dbo.employee WHERE ID > 5 and ID < 10; COMMIT;
--Transaction 2 BEGIN TRAN; INSERT INTO dbo.employee (Id, Name) VALUES(6 ,'New'); COMMIT;
Sorfrissítések által okozott hiányzó és dupla olvasások
Egy frissített sor hiányzik, vagy többször is megjelenik egy frissített sor
A
READ UNCOMMITTED
szinten futó tranzakciók (vagy aNOLOCK
táblamutatót használó utasítások) nem adnak ki megosztott zárolásokat, hogy más tranzakciók ne módosíthassák az aktuális tranzakció által beolvasott adatokat. AREAD COMMITTED
szinten futó tranzakciók megosztott zárolásokat adnak ki, de a sor- vagy oldalzárolások a sor beolvasása után szabadulnak fel. Mindkét esetben, amikor egy indexet vizsgál, ha egy másik felhasználó módosítja a sor indexkulcs oszlopát az olvasás során, a sor újra megjelenhet, ha a kulcs módosítása a sort a vizsgálat előtti pozícióba helyezte. Hasonlóképpen előfordulhat, hogy a sor egyáltalán nem lesz beolvasva, ha a kulcsmódosítás áthelyezte a sort a már beolvasott index egy helyére. Ennek elkerülése érdekében használja aSERIALIZABLE
vagy aHOLDLOCK
utasítást, vagy a sor verziózást. További információért lásd: táblázattal kapcsolatos tippek (Transact-SQL).Hiányzik egy vagy több sor, amely nem volt a frissítés célja
Ha a
READ UNCOMMITTED
-t használja, és a lekérdezés foglalási sorrend szerinti vizsgálattal (IAM-oldalak használatával) olvas be sorokat, előfordulhat, hogy a sorok kimaradnak, ha egy másik tranzakció oldalhasadást okoz. Ez nem történik meg azREAD COMMITTED
elkülönítési szint használatakor.
Az egyidejűség típusai
Ha egyszerre több tranzakció is megkísérel adatokat módosítani egy adatbázisban, vezérlőrendszert kell implementálni, hogy az egyik tranzakció módosításai ne befolyásolják hátrányosan a másik tranzakció adatait. Ezt egyidejűség-vezérlésnek nevezzük.
Az egyidejűség-vezérlés elmélete két besorolással rendelkezik az egyidejűség-vezérlési módszerekhez:
pesszimista egyidejűségvezérlés
A zárolási rendszer megakadályozza, hogy a tranzakciók más tranzakciókat érintő módon módosítsák az adatokat. Miután egy tranzakció végrehajtott egy zárolást okozó műveletet, más tranzakciók nem hajthatnak végre olyan műveleteket, amelyek ütköznének a zárolással, amíg a tulajdonos fel nem oldja azt. Ezt pesszimista vezérlésnek nevezik, mivel általában olyan rendszerekben használják, ahol nagy az adat versengés, ahol az adatok zárolással történő védelmének költsége kisebb, mint az egyidejűségi ütközések esetén a tranzakciók visszagördülésének költsége.
optimista egyidejűség-vezérlés
Az optimista egyidejűség-vezérlésben a tranzakciók nem zárolják az adatokat olvasáskor. Amikor azonban egy tranzakció frissíti az adatokat, a rendszer ellenőrzi, hogy egy másik tranzakció módosította-e az adatokat az olvasás után. Ha egy másik tranzakció frissítette az adatokat, hibaüzenet jelenik meg. A hibát kapó tranzakció általában visszafordul, és újraindul. Ezt optimistának nevezik, mivel általában olyan rendszerekben használják, ahol alacsony az adatok versengése, és ahol a tranzakciók időnkénti visszaállításának költsége alacsonyabb, mint az adatok olvasáskor történő zárolásának költsége.
Az adatbázismotor mindkét egyidejűségi vezérlési módszert támogatja. A felhasználók az egyidejűség-vezérlés típusát a kapcsolatok tranzakcióelkülönítési szintjeinek kiválasztásával vagy a kurzorokon az egyidejűségi beállítások kiválasztásával adhatók meg. Ezek az attribútumok Transact-SQL utasításokkal vagy az adatbázis-alkalmazásprogramozási felületek (API-k) tulajdonságaival és attribútumaival( például ADO, ADO.NET, OLE DB és ODBC) határozhatók meg.
Az adatbázismotor elkülönítési szintjei
A tranzakciók egy elkülönítési szintet határoznak meg, amely meghatározza, hogy egy tranzakciót milyen mértékben kell elkülöníteni a más tranzakciók által végrehajtott erőforrás- vagy adatmódosításoktól. Az elkülönítési szintek meghatározzák, hogy milyen egyidejűségi mellékhatások, például a piszkos olvasások vagy a fantomolvasások, engedélyezettek.
Tranzakcióelkülönítési szintek szabályozása:
- Hogy az adatok olvasásakor megtörténik-e a zárolás, és milyen típusú zárolásokat kérnek.
- Mennyi ideig vannak érvényben az olvasási zárolások.
- Azt jelzi, hogy egy olvasási művelet hivatkozik-e egy másik tranzakció által módosított sorokra:
- Letiltja, amíg a sor kizárólagos zárolása fel nem szabadul.
- Lekéri annak a sornak a véglegesített verzióját, amely az utasítás vagy a tranzakció elindításakor létezett.
- Beolvassa a nem véglegesített adatmódosítást.
Fontos
A tranzakcióelkülönítési szint kiválasztása nem befolyásolja az adatmódosítások védelme érdekében beszerzett zárolásokat. Egy tranzakció mindig kizárólagos zárolással rendelkezik az adatmódosítás végrehajtásához, és a zárolást a tranzakció befejezéséig tárolja, függetlenül attól, hogy az adott tranzakció elkülönítési szintje milyen szinten van megadva. Az olvasási műveletek esetében a tranzakcióelkülönítési szintek elsősorban a más tranzakciók által végrehajtott módosítások hatásai elleni védelem szintjét határozzák meg.
Az alacsonyabb elkülönítési szint növeli számos tranzakció azon képességét, hogy egyszerre férhessen hozzá az adatokhoz, de növeli az egyidejűségi hatások (például a piszkos olvasások vagy az elveszett frissítések) tranzakcióinak számát is. Ezzel szemben a magasabb elkülönítési szint csökkenti a tranzakciók által esetlegesen előforduló egyidejűségi hatásokat, de több rendszererőforrást igényel, és növeli annak esélyét, hogy az egyik tranzakció blokkolja a másikat. A megfelelő elkülönítési szint kiválasztása az alkalmazás adatintegritási követelményeinek az egyes elkülönítési szintek többletterhelésével való egyensúlyozásától függ. A legmagasabb elkülönítési szint( SERIALIZABLE
) garantálja, hogy egy tranzakció pontosan ugyanazokat az adatokat kérje le minden alkalommal, amikor egy olvasási műveletet megismétel, de ezt úgy teszi, hogy olyan zárolási szintet hajt végre, amely valószínűleg hatással lesz a többfelhasználós rendszerek más tranzakcióira. A legalacsonyabb elkülönítési szint (READ UNCOMMITTED
) lekérheti az egyéb tranzakciók által módosított, de nem véglegesített adatokat. Az egyidejűség minden mellékhatása előfordulhat a READ UNCOMMITTED
-ban, de nincs olvasási zárolás vagy verziószámozás, így a többletterhelés minimalizálódik.
Adatbázismotor elkülönítési szintjei
Az ISO-szabvány a következő elkülönítési szinteket határozza meg, amelyeket az adatbázismotor támogat:
Elkülönítési szint | Definíció |
---|---|
READ UNCOMMITTED |
A legalacsonyabb elkülönítési szint, ahol a tranzakciók csak annyira vannak elkülönítve, hogy a fizikailag inkonzisztens adatok ne legyenek beolvasva. Ebben a szinten a piszkos olvasások engedélyezettek, így előfordulhat, hogy egy tranzakció nem véglegesített módosításokat lát más tranzakciók által. |
READ COMMITTED |
Lehetővé teszi egy tranzakció számára, hogy egy másik tranzakció által korábban beolvasott (nem módosított) adatokat olvasson be anélkül, hogy az első tranzakció befejezésére vár. Az adatbázismotor a tranzakció végéig megőrzi az írási zárolásokat (amelyeket a kiválasztott adatokon szerez be), de az olvasási zárolások az olvasási művelet végrehajtása után azonnal felszabadulnak. Ez az adatbázismotor alapértelmezett szintje. |
REPEATABLE READ |
Az adatbázismotor a tranzakció végéig megőrzi a kiválasztott adatokon beszerzett olvasási és írási zárolásokat. Mivel azonban a tartományzárolások kezelése nem történik meg, fantomolvasások is előfordulhatnak. |
SERIALIZABLE |
A legmagasabb szint, ahol a tranzakciók teljesen el vannak különítve egymástól. Az adatbázismotor a tranzakció végéig megőrzi a kiválasztott adatokon beszerzett olvasási és írási zárolásokat. A tartományzárolások akkor kerülnek megszerzésre, amikor a SELECT művelet egy tartományt használó WHERE záradékot alkalmaz a fantomolvasások elkerülése érdekében. Megjegyzés: replikált táblák DDL-műveletei és tranzakciói meghiúsulhatnak, ha a SERIALIZABLE elkülönítési szintet kérik. Ennek az az oka, hogy a replikációs lekérdezések olyan tippeket használnak, amelyek nem kompatibilisek a SERIALIZABLE elkülönítési szinttel. |
Az adatbázismotor két további tranzakcióelkülönítési szintet is támogat, amelyek sorverziót használnak. Az egyik a READ COMMITTED
elkülönítési szint implementálása, az egyik pedig a SNAPSHOT
tranzakcióelkülönítési szint.
Sorverziók elkülönítési szintje | Definíció |
---|---|
Read Committed Snapshot (RCSI) |
Ha a READ_COMMITTED_SNAPSHOT adatbázis opció be van állítva ON , ami az Azure SQL Database alapértelmezett beállítása, a READ COMMITTED izolációs szint sorverziót használ az utasításszintű olvasási konzisztencia biztosításához. Az olvasási műveletekhez csak a sémastabilitás (Sch-S ) táblaszintű zárolásra van szükség, és nincs lap- vagy sorzárolás. Vagyis az adatbázismotor sorverziózással biztosít minden egyes utasításhoz egy tranzakciósan konzisztens pillanatképet az adatról, ahogyan az az utasítás elején létezett. A zárolások nem arra szolgálnak, hogy megvédjék az adatokat a más tranzakciók által végrehajtott frissítésektől. A felhasználó által definiált függvények az UDF-t tartalmazó utasítás kezdete után véglegesített adatokat adhatnak vissza.Amikor a READ_COMMITTED_SNAPSHOT adatbázis opció OFF van beállítva, ami az SQL Server és az Azure SQL Managed Instance alapértelmezettje, a READ COMMITTED izoláció megosztott zárolásokkal megakadályozza, hogy más tranzakciók módosítsák a sorokat, miközben az aktuális tranzakció olvasási műveletet végez. A megosztott zárolások azt is blokkolják, hogy az utasítás beolvassa a többi tranzakció által módosított sorokat, amíg a másik tranzakció be nem fejeződik. Mindkét implementáció megfelel READ COMMITTED elkülönítés ISO-definíciójának. |
SNAPSHOT |
A pillanatkép-elkülönítési szint a sorverziók használatával biztosítja a tranzakciószintű olvasási konzisztenciát. Az olvasási műveletek nem szereznek be lap- vagy sorzárolást; csak sémastabilitási (Sch-S ) táblazárolás történik. Amikor egy másik tranzakció által módosított sorokat olvas be, az olvasási műveletek lekérik a tranzakció indításakor létező sor verzióját. Csak akkor használhatja SNAPSHOT elkülönítést, ha a ALLOW_SNAPSHOT_ISOLATION adatbázis beállítása ON . Alapértelmezés szerint ez a beállítás OFF az SQL Server és az Azure SQL felügyelt példány felhasználói adatbázisaihoz, és ON az az Azure SQL Database adatbázisokhoz.Megjegyzés: Az adatbázismotor nem támogatja a metaadatok verziószámozását. Ezért vannak korlátozások arra vonatkozóan, hogy milyen DDL-műveletek hajthatók végre egy pillanatkép-elkülönítéssel futó explicit tranzakcióban. A következő DDL-utasítások nem engedélyezettek a pillanatképek elkülönítése során egy BEGIN TRANSACTION utasítás után: ALTER TABLE , CREATE INDEX , CREATE XML INDEX , ALTER INDEX , DROP INDEX , DBCC REINDEX , ALTER PARTITION FUNCTION , ALTER PARTITION SCHEME vagy bármely közös nyelvi futtatókörnyezeti (CLR) DDL-utasítás. Ezek az állítások engedélyezettek, amikor implicit tranzakciókon belül pillanatkép-elkülönítést használ. Az implicit tranzakció definíció szerint egy olyan utasítás, amely lehetővé teszi a pillanatkép izoláció szemantikájának érvényesítését, még DDL-utasítások mellett is. Ennek az alapelvnek a megsértése 3961-et okozhat: Snapshot isolation transaction failed in database '%.*ls' because the object accessed by the statement has been modified by a DDL statement in another concurrent transaction since the start of this transaction. It is not allowed because the metadata is not versioned. A concurrent update to metadata could lead to inconsistency if mixed with snapshot isolation. |
Az alábbi táblázat a különböző elkülönítési szintek által engedélyezett egyidejűségi mellékhatásokat mutatja be.
Elkülönítési szint | Piszkos olvasás | Nem megismételhető olvasás | Fantom |
---|---|---|---|
READ UNCOMMITTED |
Igen | Igen | Igen |
READ COMMITTED |
Nem | Igen | Igen |
REPEATABLE READ |
Nem | Nem | Igen |
SNAPSHOT |
Nem | Nem | Nem |
SERIALIZABLE |
Nem | Nem | Nem |
Az egyes tranzakcióelkülönítési szintek által szabályozott zárolási vagy sorverziós típusokkal kapcsolatos további információkért lásd SET TRANSACTION ISOLATION LEVEL (Transact-SQL).
A tranzakcióelkülönítési szinteket Transact-SQL vagy adatbázis API-val lehet beállítani.
Transact-SQL
Transact-SQL szkriptek a SET TRANSACTION ISOLATION LEVEL
utasítást használják.
ADO
Az ADO-alkalmazások a IsolationLevel
objektum Connection
tulajdonságát adXactReadUncommitted
, adXactReadCommitted
, adXactRepeatableRead
vagy adXactReadSerializable
értékre állítják be.
ADO.NET
ADO.NET System.Data.SqlClient
felügyelt névteret használó alkalmazások meghívhatják a SqlConnection.BeginTransaction
metódust, és beállíthatják a IsolationLevel
beállítást Unspecified
, Chaos
, ReadUncommitted
, ReadCommitted
, RepeatableRead
, Serializable
vagy Snapshot
.
OLE DB
Tranzakció indításakor az OLE DB-t használó alkalmazások a ITransactionLocal::StartTransaction
függvényt hívják meg úgy, hogy a isoLevel
értéke ISOLATIONLEVEL_READUNCOMMITTED
, ISOLATIONLEVEL_READCOMMITTED
, ISOLATIONLEVEL_REPEATABLEREAD
, ISOLATIONLEVEL_SNAPSHOT
vagy ISOLATIONLEVEL_SERIALIZABLE
.
A tranzakcióelkülönítési szint autocommit módban történő megadásakor az OLE DB-alkalmazások a DBPROPSET_SESSION
tulajdonság DBPROP_SESS_AUTOCOMMITISOLEVELS
ot DBPROPVAL_TI_CHAOS
, DBPROPVAL_TI_READUNCOMMITTED
, DBPROPVAL_TI_BROWSE
, DBPROPVAL_TI_CURSORSTABILITY
, DBPROPVAL_TI_READCOMMITTED
, DBPROPVAL_TI_REPEATABLEREAD
, DBPROPVAL_TI_SERIALIZABLE
, DBPROPVAL_TI_ISOLATED
vagy DBPROPVAL_TI_SNAPSHOT
értékre állíthatják.
ODBC
Az ODBC-alkalmazások hívják a SQLSetConnectAttr
-t úgy, hogy a Attribute
értéke SQL_ATTR_TXN_ISOLATION
, a ValuePtr
értéke pedig SQL_TXN_READ_UNCOMMITTED
, SQL_TXN_READ_COMMITTED
, SQL_TXN_REPEATABLE_READ
vagy SQL_TXN_SERIALIZABLE
.
Pillanatkép-tranzakciók esetén az alkalmazások a SQLSetConnectAttr
-t hívják meg, ahol az Attribútum be van állítva SQL_COPT_SS_TXN_ISOLATION
-re, és ValuePtr
be van állítva a SQL_TXN_SS_SNAPSHOT
-ra. A pillanatkép-tranzakciók SQL_COPT_SS_TXN_ISOLATION
vagy SQL_ATTR_TXN_ISOLATION
használatával kérhetők le.
Zárolás az adatbázismotorban
A zárolás az adatbázismotor által használt mechanizmus, amellyel egyszerre több felhasználó is szinkronizálhatja ugyanahhoz az adathoz való hozzáférést.
Mielőtt egy tranzakció függőséget szerez egy adat aktuális állapotától, például az adatok olvasásával vagy módosításával, meg kell védenie magát egy másik, ugyanazon adatokat módosító tranzakció hatásaitól. A tranzakció ezt úgy teszi meg, hogy zárolást kér az adatrészen. A zárolások különböző módokkal rendelkeznek, például megosztott (S
) vagy kizárólagos (X
). A zárolási mód határozza meg, hogy a tranzakció milyen függőségi szinttel rendelkezik az adatokon. Nem adható zárolás egy tranzakcióhoz, amely ellentmondana annak a zárolási módnak, amelyet már megadtak az adatra egy másik tranzakció számára. Ha egy tranzakció olyan zárolási módot kér, amely ütközik az ugyanazon adatokon már megadott zárolással, az adatbázismotor az első zárolás feloldásáig szünetelteti a kérési tranzakciót.
Amikor egy tranzakció módosít egy adatrészt, bizonyos zárolások védik a módosítást a tranzakció végéig. Az, hogy egy tranzakció milyen hosszú ideig tartja meg az olvasási műveletek védelme érdekében beszerzett zárolásokat, a tranzakciók elszigeteltségi szint beállításától és attól függ, hogy a optimalizált zárolás engedélyezve van-e.
Ha az optimalizált zárolás nincs engedélyezve, az íráshoz szükséges sor- és oldalzárolások a tranzakció végéig lesznek megtartva.
Ha az optimalizált zárolás engedélyezve van, a tranzakció végéig csak a tranzakcióazonosító (TID) zárolása lesz megtartva. Az alapértelmezett
READ COMMITTED
elkülönítési szinten a tranzakciók a tranzakció végéig nem fogják tárolni az íráshoz szükséges sor- és oldalzárolásokat. Ez csökkenti a szükséges zárolási memóriát, és csökkenti a zárolás eszkalálásának szükségességét. Továbbá, ha az optimalizált zárolás engedélyezve van, a minősítés utáni zárolás (LAQ) optimalizálás kiértékeli a lekérdezések predikátumait a sor legújabb véglegesített verzióján anélkül, hogy zárolást szerezné be, javítva ezzel az egyidejűséget.
A tranzakció által tartott összes zárolás felszabadul, amikor a tranzakció befejeződik (akár véglegesítés, akár visszaállítás esetén).
Az alkalmazások általában nem kérnek zárolást közvetlenül. A zárolásokat a zároláskezelő nevű adatbázismotor egy része belsőleg kezeli. Amikor az adatbázismotor egy példánya feldolgoz egy Transact-SQL utasítást, az adatbázismotor lekérdezésfeldolgozója határozza meg, hogy mely erőforrásokhoz kell hozzáférni. A lekérdezésfeldolgozó határozza meg, hogy milyen típusú zárolások szükségesek az egyes erőforrások védelméhez a hozzáférés típusa és a tranzakcióelkülönítési szint beállítása alapján. A lekérdezésfeldolgozó ezután kéri a megfelelő zárolásokat a zároláskezelőtől. A zároláskezelő engedélyezi a zárolásokat, ha nincsenek más tranzakciók által tartott ütköző zárolások.
Zárolási finomság és hierarchiák
Az adatbázismotor többtényezős zárolással rendelkezik, amely lehetővé teszi a különböző típusú erőforrások tranzakció általi zárolását. A zárolási költségek minimalizálása érdekében az adatbázismotor automatikusan zárolja az erőforrásokat a feladatnak megfelelő szinten. A kisebb részletességű zárolás, például a sorok növelik az egyidejűséget, de nagyobb a terhelés, mivel több zárolást kell tartani, ha sok sor zárolva van. A nagyobb részletességű zárolások, például a táblák, az egyidejűség szempontjából költségesek, mivel egy teljes tábla zárolása más tranzakciók által korlátozza a tábla bármely részéhez való hozzáférést. Azonban ennek alacsonyabb a túlterhelése, mivel kevesebb zár van fenntartva.
Az adatbázismotornak gyakran több részletességi szinten kell zárolásokat szereznie az erőforrások teljes védelméhez. Ezt a több részletességi szinten lévő zároláscsoportot zárolási hierarchiának nevezzük. Egy index olvasásának teljes védelméhez például előfordulhat, hogy az adatbázismotor egy példányának megosztott zárolásokat kell beszereznie a sorokon, és szándék szerinti megosztott zárolásokat kell beszereznie az oldalakon és a táblán.
Az alábbi táblázat azokat az erőforrásokat mutatja be, amelyeket az adatbázismotor zárolhat.
Erőforrás | Leírás |
---|---|
RID |
Egy sorazonosító, amellyel egyetlen sort zárolunk a halomban. |
KEY |
Egyetlen sor zárolása egy B-fa indexben. |
PAGE |
Egy adatbázis 8 kilobájtos (KB) lapja, például adatok vagy indexlapok. |
EXTENT |
Nyolc oldalból álló egybefüggő csoport, például adatok vagy indexlapok. |
HoBT
1 |
Halom vagy B-fa. Egy zárolás, amely a B-fa (index) vagy a halom adatoldalait védi egy olyan táblában, amely nem tartalmaz tömbösített indexet. |
TABLE
1 |
A teljes táblázat, beleértve az összes adatot és indexet. |
FILE |
Egy adatbázisfájl. |
APPLICATION |
Egy alkalmazás által megadott erőforrás. |
METADATA |
Metaadatok zárolása. |
ALLOCATION_UNIT |
Egy elosztási egység. |
DATABASE |
A teljes adatbázis. |
XACT
2 |
optimalizált zárolásában használt tranzakcióazonosító (TID) zárolása. További információért lásd a tranzakcióazonosító (TID) zárolása. |
1HoBT
és TABLE
zárolást az ALTER TABLE LOCK_ESCALATION
lehetősége befolyásolhatja.
2 További zárolási erőforrások állnak rendelkezésre a XACT
zárolási erőforrásokhoz, lásd a diagnosztikai kiegészítéseket az optimalizált zárolás érdekében.
Zárolási módok
Az adatbázismotor különböző zárolási módok használatával zárolja az erőforrásokat, amelyek meghatározzák, hogy az erőforrások hogyan érhetők el egyidejű tranzakciókkal.
Az alábbi táblázat az adatbázismotor által használt erőforrás-zárolási módokat mutatja be.
Zárolási mód | Leírás |
---|---|
megosztott (S ) |
Olyan olvasási műveletekhez használható, amelyek nem módosítják vagy frissítik az adatokat, például egy SELECT utasításhoz. |
Frissítés (U ) |
Frissíthető erőforrásokon használható. Megakadályozza a holtpont gyakori formáját, amely akkor fordul elő, ha több munkamenet olvas, zárol és esetleg frissít később erőforrásokat. |
Exkluzív (X ) |
Adatmódosítási műveletekhez, például INSERT , UPDATE vagy DELETE . Biztosítja, hogy egyszerre több frissítés ne legyen ugyanazon az erőforráson. |
szándék | Zárolási hierarchia létrehozására szolgál. A szándékzárolások típusai a következők: szándékmegosztás (IS ), szándék kizárólagos (IX ), és megosztott szándék kizárólagossággal (SIX ). |
séma | Akkor használatos, ha egy tábla sémáján alapuló művelet végrehajtása folyamatban van. A sémazárolások típusai a következők: sémamódosítás (Sch-M ) és sémastabilitás (Sch-S ). |
Tömeges frissítés (BU ) |
Adatok tömeges másolásakor használatos egy táblába a TABLOCK tipp használatával. |
kulcstartomány | A SERIALIZABLE tranzakcióelkülönítési szint használatakor védi a lekérdezés által beolvasott sorok tartományát. Biztosítja, hogy más tranzakciók nem szúrhatnak be olyan sorokat, amelyek a SERIALIZABLE tranzakció lekérdezéseinek megfelelőek lennének, ha a lekérdezések újra futnának. |
Megosztott zárolások
A megosztott (S
) zárolások lehetővé teszik az egyidejű tranzakciók számára, hogy pesszimista egyidejűség-vezérlés alatt olvassák be az erőforrásokat. Más tranzakciók nem módosíthatják az adatokat, miközben megosztott (S
) zárolások léteznek az erőforráson. Az erőforrás megosztott (S
) zárolásai az olvasási művelet befejeződése után azonnal feloldódnak, kivéve, ha a tranzakció elkülönítési szintje REPEATABLE READ
vagy magasabb, vagy zárolási tippet használ a megosztott (S
) zárolások megőrzéséhez a tranzakció időtartamára.
Zárolások frissítése
Az adatbázismotor a frissítés végrehajtására való felkészülés során zárolja a frissítési (U
) zárolásokat.
U
zárolások kompatibilisek S
zárolásokkal, de egy adott erőforráson egyszerre csak egy tranzakció képes U
zárolást tárolni. Ez kulcs – számos egyidejű tranzakció képes S
zárolások tárolására, de csak egy tranzakció képes U
zárolást tárolni egy erőforráson. A frissítési (U
) zárolások végül exkluzív (X
) zárolásokká alakulnak át egy sor frissítéséhez.
A frissítési (U
) zárolásokat a UPDATE
kivételével más utasítások is létrehozhatják, amikor az utasításban meg van adva az UPDLOCK táblamutató.
Egyes alkalmazások a "sor kijelölése, majd a sor frissítése" mintát használják, ahol az olvasás és az írás explicit módon különül el a tranzakción belül. Ebben az esetben, ha az elkülönítési szint
REPEATABLE READ
vagySERIALIZABLE
, az egyidejű frissítések holtpontot okozhatnak az alábbiak szerint:A tranzakció beolvassa az adatokat, megosztott (
S
) zárolást szerez az erőforráson, majd módosítja az adatokat, amely kizárólagos (X
) zárolássá való átalakítást igényel. Ha két tranzakció közös (S
) zárolást szerez be egy erőforráson, majd megkísérli az adatok egyidejű frissítését, egy tranzakció egy kizárólagos (X
) zárolásra kísérli meg a zárolás konvertálását. A megosztott-kizárólagos zárolás konvertálásának várnia kell, mert az egyik tranzakció kizárólagos (X
) zárolása nem kompatibilis a másik tranzakció megosztott (S
) zárolásával; zárolási várakozás történik. A második tranzakció egy kizárólagos (X
) zárolást kísérel meg beszerezni a frissítéshez. Mivel mindkét tranzakció kizárólagos (X
) zárolássá alakul át, és mind arra várnak, hogy a másik tranzakció feloldja a megosztott (S
) zárolást, holtpont lép fel.Az alapértelmezett
READ COMMITTED
elkülönítési szinten aS
zárolások rövid időtartamúak, és a használatuk után azonnal felszabadulnak. Bár a fent leírt holtpont továbbra is lehetséges, a rövid időtartamú zárolások sokkal kevésbé valószínűek.Az ilyen típusú holtpont elkerülése érdekében az alkalmazások követhetnek egy "válasszon egy sort
UPDLOCK
tipptel, majd frissítse a sort" mintát.Ha a
UPDLOCK
tippet íráskor használják, amikorSNAPSHOT
izoláció van érvényben, a tranzakciónak hozzá kell férnie a sor legújabb verziójához. Ha a legújabb verzió már nem látható,Msg 3960, Level 16, State 2 Snapshot isolation transaction aborted due to update conflict
fogadható. Például lásd: A pillanatkép-izolációval való munka.
Exkluzív zárolások
A kizárólagos (X
) zárolások egyidejű tranzakciókkal megakadályozzák az erőforrások elérését. Kizárólagos (X
) zárolással más tranzakciók nem módosíthatják a zárolás által védett adatokat; olvasási műveletek csak a NOLOCK
tipp vagy a READ UNCOMMITTED
elkülönítési szint használatával történhetnek.
Az adatmódosítási utasítások, például INSERT
, UPDATE
és DELETE
olvasási és módosítási műveleteket is kombinálnak. Az utasítás először olvasási műveleteket hajt végre az adatok beszerzéséhez a szükséges módosítási műveletek végrehajtása előtt. Az adatmódosítási utasítások ezért általában a megosztott zárolásokat és a kizárólagos zárolásokat is kérik. Egy UPDATE
utasítás például módosíthatja az egyik tábla sorait egy másik táblával való összekapcsolás alapján. Ebben az esetben a UPDATE
utasítás a frissített sorok kizárólagos zárolásának kérése mellett az illesztési táblázatban beolvasott sorok közös zárolását is kéri.
Szándékzárak
Az adatbázismotor szándékzárak használatával védi a megosztott (S
) zárolást vagy a kizárólagos (X
) zárolást a zárolási hierarchiában alacsonyabb erőforráson. A szándékzárak azért kapják ezt a nevet, mert azokat az alsó szinten lévő zárolások előtt szerzik meg, jelezvén a szándékot az alsó szinti zárolások elhelyezésére.
A szándékzárak két célt szolgálnak:
- Annak megakadályozására, hogy más tranzakciók úgy módosítsák a magasabb szintű erőforrást, amely érvénytelenítené a zárolást az alacsonyabb szinten.
- Az adatbázismotor hatékonyságának javítása a zárolási ütközések magasabb részletességi szinten történő észlelésében.
A megosztott szándék zárolását például a rendszer a tábla szintjén kéri, mielőtt a megosztott (S
) zárolásokat a rendszer az adott táblán belüli oldalakon vagy sorokban kéri. A szándék zárolásának táblaszintű beállítása megakadályozza, hogy egy másik tranzakció később kizárólagos (X
) zárolást szerezzen be az oldalt tartalmazó táblán. A szándékzárolások javítják a teljesítményt, mert az adatbázismotor csak a tábla szintjén vizsgálja meg a szándékzárolásokat annak megállapításához, hogy egy tranzakció képes-e biztonságosan zárolni az adott táblát. Ez eltávolítja azt a követelményt, hogy vizsgálja meg a tábla minden sor- vagy oldalzárolását annak megállapításához, hogy egy tranzakció zárolhatja-e a teljes táblát.
szándékzárak közé tartoznak a szándék közös (IS
), szándék kizárólagos (IX
), és a közös szándék a kizárólagossal (SIX
).
Zárolási mód | Leírás |
---|---|
szándék megosztott (IS ) |
Védi a kért vagy beszerzett megosztott zárolásokat a hierarchia egyes (de nem minden) erőforrásán. |
Szándék kizárólagos (IX ) |
Védi a hierarchiában alacsonyabb szintű (de nem minden) erőforrásokon lévő kért vagy megszerzett kizárólagos zárolásokat.
IX a IS szuperhalmaza, és az alacsonyabb szintű erőforrások megosztott zárolásának kérését is védi. |
Megosztva kizárólagos szándékkal (SIX ) |
Védelmezi a kérésre vagy megszerzett megosztott zárolásokat a hierarchiában alacsonyabb szintű erőforrásokon, és némelyik (de nem az összes) alacsonyabb szintű erőforrásra vonatkozóan szándékozottan kizárólagos zárolásokat is alkalmaz. A legfelső szintű erőforrásnál megengedettek az egyidejű IS zárolások. Például, amikor egy SIX zárolást szerez egy táblán, az a módosított oldalakon szándékos kizárólagos zárolásokat, és a módosított sorokon kizárólagos zárolásokat is szerez. Egyszerre csak egy SIX zárolás lehet erőforrásonként, ami megakadályozza az erőforrás más tranzakciók által végzett frissítéseit, bár más tranzakciók a IS zárolások táblaszinten történő lekérésével a hierarchiában alacsonyabb szintű erőforrásokat is beolvashatnak. |
szándékfrissítés (IU ) |
Védi a kért vagy beszerzett frissítési zárolásokat a hierarchiában alacsonyabb erőforrásokon.
IU zárolások csak laperőforrásokon használhatók.
IU zárolások IX zárolássá alakulnak, ha frissítési művelet történik. |
Megosztott szándékfrissítés (SIU ) |
A S és a IU zárak kombinációja, amely a zárak külön-külön történő megszerzésének eredménye, és egyidejűleg mindkét zárat tartják. Egy tranzakció például végrehajt egy lekérdezést a PAGLOCK tipptel, majd végrehajt egy frissítési műveletet. A PAGLOCK tippet tartalmazó lekérdezés megszerzi a S zárolást, és a frissítési művelet pedig megszerzi a IU zárolást. |
Kizárólagos frissítési szándék (UIX ) |
A U és a IX zárak kombinációja, amely a zárak külön-külön történő megszerzésének eredménye, és egyidejűleg mindkét zárat tartják. |
Sémazárolások
Az adatbázismotor sémamódosítási (Sch-M
) zárolásokat használ a tábla adatdefiníciós nyelvének (DDL) művelete során, például oszlop hozzáadása vagy tábla elvetése során. A Sch-M
zárolás ideje alatt megakadályozza a tábla egyidejű elérését. Ez azt jelenti, hogy a Sch-M
zárolás blokkolja az összes külső műveletet a zárolás feloldásáig.
Egyes adatmanipulációs nyelvi (DML-) műveletek, mint például a táblacsonkítás, Sch-M
zárolásokkal akadályozzák meg az érintett táblákhoz való hozzáférést az egyidejű műveletek során.
Az adatbázismotor sémastabilitási (Sch-S
) zárolásokat használ a lekérdezések összeállításakor és végrehajtásakor. A Sch-S
zárolások nem akadályozzák meg a tranzakciós zárolásokat, beleértve a kizárólagos (X
) zárolásokat sem. Ezért a lekérdezés összeállítása során a többi tranzakció, beleértve azokat is, amelyek X
zárolást tartalmaznak egy táblán, továbbra is futnak. Az egyidejű DDL-műveleteket és az egyidejű DML-műveleteket, amelyek Sch-M
zárolásokat szereznek be, a Sch-S
zárolások blokkolják.
Tömeges frissítési zárolások
A tömeges frissítési (BU
) zárolások lehetővé teszik, hogy több szál egyidejűleg tömegesen betöltse az adatokat ugyanabba a táblába, ugyanakkor megakadályozza, hogy más folyamatok is hozzáférhessenek a táblához, amelyek nem töltik be tömegesen az adatokat. Az adatbázismotor tömeges frissítési (BU
) zárolásokat használ, ha az alábbi feltételek mindegyike teljesül.
- A Transact-SQL
BULK INSERT
utasítást vagy aOPENROWSET(BULK)
függvényt használja, vagy a Tömeges beszúrás API-parancsok egyikét, például a .NETSqlBulkCopy
, az OLEDB Fast Load API-kat vagy az ODBC Tömeges másolás API-kat használja az adatok tömeges másolásához egy táblába. - Meg van adva a
TABLOCK
tipp, vagy atable lock on bulk load
táblabeállítás a sp_tableoptionhasználatával van beállítva.
Borravaló
Ellentétben a BULK INSERT utasítással, amely kevésbé korlátozó tömeges frissítési (BU
) zárolást tartalmaz, INSERT INTO...SELECT
a TABLOCK
tipptel egy szándékkizárási (IX
) zárolást tartalmaz a táblán. Ez azt jelenti, hogy párhuzamos beszúrási műveletekkel nem szúrhat be sorokat.
kulcstartományos zárolások
A kulcstartomány-zárolások a SERIALIZABLE
tranzakcióelkülönítési szint használata során a rekordhalmazba implicit módon belefoglalt sortartományokat védik, amelyeket egy Transact-SQL utasítás olvas be. A kulcstartomány-zárolás megakadályozza a fantom olvasatokat. A kulcsok sorok közötti tartományainak védelmével megakadályozza, hogy fantom módosítások, például beszúrások vagy törlések történjenek a tranzakcióval elért rekordhalmazban.
Kompatibilitás zárolása
A zárolás kompatibilitása szabályozza, hogy egyszerre több tranzakció képesek-e zárolásokat szerezni ugyanazon az erőforráson. Ha egy erőforrást már zárolt egy másik tranzakció, új zárolási kérelem csak akkor adható meg, ha a kért zárolás módja kompatibilis a meglévő zárolás módjával. Ha a kért zárolás módja nem kompatibilis a meglévő zárolással, az új zárolást kérő tranzakció megvárja a meglévő zárolás feloldását vagy a zárolási időkorlát lejáratát. Például egyetlen zárolási mód sem kompatibilis a kizárólagos zárolásokkal. Bár kizárólagos (X
) zárolás van tárolva, más tranzakció nem szerezhet be semmilyen (megosztott, frissítési vagy kizárólagos) zárolást az adott erőforráson, amíg a kizárólagos (X
) zárolás ki nem szabadul. Ezzel szemben, ha egy megosztott (S
) zárolást alkalmaztak egy erőforrásra, más tranzakciók is beszerezhetnek megosztott zárolást vagy frissítési (U
) zárolást az erőforráson akkor is, ha az első tranzakció még nem fejeződött be. Más tranzakciók azonban csak a megosztott zárolás feloldásáig szerezhetnek be kizárólagos zárolást.
Az alábbi táblázat a leggyakrabban előforduló zárolási módok kompatibilitását mutatja be.
Meglévő megadott mód | IS |
S |
U |
IX |
SIX |
X |
---|---|---|---|---|---|---|
Kért mód | ||||||
szándék megosztott (IS ) |
Igen | Igen | Igen | Igen | Igen | Nem |
megosztott (S ) |
Igen | Igen | Igen | Nem | Nem | Nem |
Frissítés (U ) |
Igen | Igen | Nem | Nem | Nem | Nem |
Szándék kizárólagos (IX ) |
Igen | Nem | Nem | Igen | Nem | Nem |
Megosztva kizárólagos szándékkal (SIX ) |
Igen | Nem | Nem | Nem | Nem | Nem |
Exkluzív (X ) |
Nem | Nem | Nem | Nem | Nem | Nem |
Jegyzet
A kizárólagos szándékú (IX
) zárolás kompatibilis a IX
zárolási móddal, mert IX
azt jelenti, hogy a cél az, hogy csak néhány sort frissítsen, nem pedig az összeset. A sorok egy részének olvasását vagy frissítését megkísérlő egyéb tranzakciók is engedélyezettek, feltéve, hogy azok nem ugyanazok a sorok, amelyeket más tranzakciók frissítenek. Továbbá, ha két tranzakció megpróbálja frissíteni ugyanazt a sort, mindkét tranzakció IX
zárolást kap a táblázat és az oldal szintjén. Azonban egy tranzakció sor szintjén X
zárolást kaphat. A másik tranzakciónak várnia kell, amíg a sorszintű zárolás el nem távolítódik.
Az alábbi táblázat segítségével állapítsa meg az adatbázismotorban elérhető összes zárolási mód kompatibilitását.
Kulcs | Leírás |
---|---|
N | Nincs ütközés |
Én | Törvénytelen |
C | Konfliktus |
Hollandia | Nincs zárolás |
SCH-S | Sémastabilitás zárolása |
SCH-M | Séma módosításának zárolása |
S | Megosztott |
U | Frissít |
X | Exkluzív |
VAN | Szándék megosztva |
NE | Szándék módosítása |
9 | Kizárólagossági jog |
SIU | Megosztás frissítési szándékkal |
HAT | Megosztás kizárólagos szándékkal |
UIX | Szándék szerint kizárólagos frissítés |
BU | Tömeges frissítés |
RS-S | Megosztott tartomány - megosztva |
RS-U | Megosztott tartomány frissítése |
RI-N | Tartomány-null érték beszúrása |
RI-S | Megosztott tartomány beszúrása |
RI-U | Tartományfrissítés beillesztése |
RI-X | Kizárólagos tartomány beszúrása |
RX-S | Kizárólagosan megosztott tartomány |
RX-U | Kizárólagos hatókörfrissítés |
RX-X | Kizárólagos készlet-kizárólagos |
Kulcstartomány zárolása
A kulcstartomány-zárolások a SERIALIZABLE
tranzakcióelkülönítési szint használata során a rekordhalmazba implicit módon belefoglalt sortartományokat védik, amelyeket egy Transact-SQL utasítás olvas be. A SERIALIZABLE
elkülönítési szint megköveteli, hogy a tranzakció során végrehajtott lekérdezések minden alkalommal ugyanazokat a sorokat kapják meg, amikor a tranzakció során végrehajtják. A kulcstartomány-zárolás megfelel ennek a követelménynek, mert megakadályozza, hogy más tranzakciók olyan új sorokat szúrnak be, amelyek kulcsai a SERIALIZABLE
tranzakció által beolvasott kulcstartományba esnének.
A kulcstartomány-zárolás megakadályozza a fantom olvasatokat. A sorok közötti kulcstartományok védelmével megakadályozza a tranzakció által elért rekordoknál a fantom beszúrásokat is.
A kulcstartomány-zárolás egy indexre kerül elhelyezésre, meghatározva egy kezdő és egy záró kulcsértéket. Ez a zárolás letiltja a tartományba eső kulcsértékkel rendelkező sorok beszúrására, frissítésére vagy törlésére tett kísérleteket, mivel ezeknek a műveleteknek először zárolást kell szerezniük az indexen. Egy SERIALIZABLE
tranzakció például kibocsáthat egy SELECT
utasítást, amely beolvassa az összes sort, amelynek kulcsértékei megfelelnek a BETWEEN 'AAA' AND 'CZZ'
feltételnek. A 'AAA' ' 'CZZ' tartomány kulcsértékeinek kulcstartomány-zárolása megakadályozza, hogy más tranzakciók a tartomány bármely pontján kulcsértékekkel rendelkező sorokat szúrjanak be, például 'ADG', 'BBD', vagy 'CAL'.
Zárolási módok kulcstartományokhoz
A kulcstartomány-zárolások tartománysor formátumban megadott tartományt és sorösszetevőt is tartalmaznak:
- A tartomány azt a zárolási módot jelöli, amely két egymást követő indexbejegyzés közötti tartományt védi.
- A sor az indexbejegyzést védő zárolási módot jelöli.
- A mód a használt kombinált zárolási módot jelöli. A kulcstartományos zárolási módok két részből állnak. Az első az indextartomány zárolásához használt zárolás típusát (TartományT) jelöli, a második pedig az adott kulcs zárolásához használt zárolástípust (K). A két rész egy kötőjelhez (-) csatlakozik, például a TartományT-K.
Tartomány | Sor | Üzemmód | Leírás |
---|---|---|---|
RangeS |
S |
RangeS-S |
Megosztott tartomány, megosztott erőforrás zárolása; SERIALIZABLE tartományvizsgálat. |
RangeS |
U |
RangeS-U |
Megosztott tartomány, erőforrás-zárolás frissítése; SERIALIZABLE frissítési vizsgálat. |
RangeI |
Null |
RangeI-N |
A tartomány beszúrása, null erőforrás-zár; új kulcs indexbe való beszúrása előtt a tartományok tesztelésére használják. |
RangeX |
X |
RangeX-X |
Kizárólagos tartomány, kizárólagos erőforrás-zárolás; egy tartomány kulcsának frissítésekor használható. |
Jegyzet
A belső Null
zárolási mód kompatibilis az összes többi zárolási móddal.
A kulcstartomány-zárolási módok kompatibilitási mátrixa azt mutatja, hogy mely zárolások kompatibilisek az átfedésben lévő kulcsokon és tartományokon beszerzett többi zárolással.
Meglévő megadott mód | S |
U |
X |
RangeS-S |
RangeS-U |
RangeI-N |
RangeX-X |
---|---|---|---|---|---|---|---|
Kért mód | |||||||
megosztott (S ) |
Igen | Igen | Nem | Igen | Igen | Igen | Nem |
Frissítés (U ) |
Igen | Nem | Nem | Igen | Nem | Igen | Nem |
Exkluzív (X ) |
Nem | Nem | Nem | Nem | Nem | Igen | Nem |
RangeS-S |
Igen | Igen | Nem | Igen | Igen | Nem | Nem |
RangeS-U |
Igen | Nem | Nem | Igen | Nem | Nem | Nem |
RangeI-N |
Igen | Igen | Igen | Nem | Nem | Igen | Nem |
RangeX-X |
Nem | Nem | Nem | Nem | Nem | Nem | Nem |
Konverziós zárolások
A konvertálási zárolások akkor jönnek létre, ha egy kulcstartomány-zárolás átfedésben van egy másik zárolással.
1. zár | Zárolás 2 | Konverziós zárolás |
---|---|---|
S |
RangeI-N |
RangeI-S |
U |
RangeI-N |
RangeI-U |
X |
RangeI-N |
RangeI-X |
RangeI-N |
RangeS-S |
RangeX-S |
RangeI-N |
RangeS-U |
RangeX-U |
A konverziós zárolások rövid ideig figyelhetők meg különböző összetett körülmények között, néha egyidejű folyamatok futtatásakor.
Szerializálható tartomány vizsgálata, egyszeri beolvasás, törlés és beszúrás
A kulcstartomány-zárolás biztosítja, hogy a következő műveletek szerializálhatók legyenek:
- Tartományvizsgálati lekérdezés
- Nem létező sor egyszeri lekérdezése
- Törlési művelet
- Beszúrás művelete
A kulcstartomány zárolása előtt a következő feltételeknek kell teljesülniük:
- A tranzakcióelkülönítési szintet
SERIALIZABLE
kell beállítani. - A lekérdezésfeldolgozónak indexet kell használnia a tartományszűrő-predikátum implementálásához. Egy
WHERE
utasításSELECT
záradéka például létrehozhat egy tartományfeltételt a következő predikátummal:ColumnX BETWEEN N'AAA' AND N'CZZ'
. Kulcs-tartomány-zárolás csak akkor szerezhető meg, haColumnX
indexkulcs fedi le.
Példák
Az alábbi táblázat és index az alábbi kulcstartomány-zárolási példák alapjául szolgál.
Tartományvizsgálati lekérdezés
Annak érdekében, hogy a tartományvizsgálati lekérdezés szerializálható legyen, ugyanazon lekérdezésnek ugyanazokat az eredményeket kell visszaadnia minden alkalommal, amikor ugyanazon a tranzakción belül hajtják végre. Más tranzakciók nem szúrhatnak be új sorokat a tartományvizsgálati lekérdezésbe; ellenkező esetben ezek fantom beszúrásokká válnak. Az alábbi lekérdezés például az előző ábrán szereplő táblát és indexet használja:
SELECT name
FROM mytable
WHERE name BETWEEN 'A' AND 'C';
A kulcstartomány-zárolások azon sortartománynak megfelelő indexbejegyzésekre kerülnek, ahol a név a Adam
és a Dale
értékek között van, megakadályozva, hogy az előző lekérdezésben megfelelő új sorok kerüljenek hozzáadásra vagy törlésre. Bár ennek a tartománynak az első neve Adam
, az indexbejegyzés RangeS-S
módú kulcstartomány-zárolása biztosítja, hogy a A
betűvel kezdődő új nevek ne legyenek hozzáadva Adam
előtt, például Abigail
. Hasonlóképpen, a RangeS-S
indexbejegyzésének Dale
kulcstartomány-zárolása biztosítja, hogy a C
betűvel kezdődő új nevek nem vehetők fel Carlos
után , például Clive
.
Jegyzet
A tárolt RangeS-S
zárolások száma n+1, ahol n a lekérdezésnek megfelelő sorok száma.
Nem létező adatok egyszeri beolvasása
Ha egy tranzakción belüli lekérdezés olyan sort próbál kijelölni, amely nem létezik, a lekérdezést egy későbbi időpontban, ugyanazon a tranzakción belül kibocsátva ugyanazt az eredményt kell visszaadnia. Ezt a nem létező sort nem lehet más tranzakcióval beszúrni. Például, adott egy ilyen lekérdezés:
SELECT name
FROM mytable
WHERE name = 'Bill';
A rendszer kulcstartomány-zárolást helyez el a névtartománynak megfelelő indexbejegyzésen Ben
és Bing
között, mert a név Bill
a két szomszédos indexbejegyzés közé lesz beszúrva. A RangeS-S
mód kulcstartomány-zárolása az indexbejegyzés Bing
helyére van elhelyezve. Ez megakadályozza, hogy bármely más tranzakció értékeket szúrjon be, például Bill
az indexbejegyzések közé Ben
és Bing
.
Optimalizált zárolás nélküli törlési művelet
Ha töröl egy sort egy tranzakción belül, a sorba eső tartományt nem kell zárolni a törlési műveletet végrehajtó tranzakció időtartamára. A törölt kulcsérték zárolása a tranzakció végéig elegendő a szerializálhatóság fenntartásához. Például tekintsük ezt a DELETE
utasítást:
DELETE mytable
WHERE name = 'Bob';
A X
névnek megfelelő indexbejegyzésre kizárólagos (Bob
) zárolás kerül. Más tranzakciók beszúrhatnak vagy törölhetnek értékeket a sor előtt vagy után a törölt Bob
értékkel. A Bob
értéknek megfelelő sorokat beolvasni, beszúrni vagy törölni próbáló tranzakciók azonban mindaddig le lesznek tiltva, amíg a törlési tranzakció véglegesítésre vagy visszaállításra nem kerül. (Az READ_COMMITTED_SNAPSHOT
adatbázis-beállítás és a SNAPSHOT
elkülönítési szint is lehetővé teszi az olvasást a korábban véglegesített állapot sorverziójából.)
A tartománytörlés három alapvető zárolási móddal hajtható végre: sor, oldal vagy táblazárolás. A sor-, oldal- vagy táblazárolási stratégiát a Lekérdezésoptimalizáló határozza meg, vagy a felhasználó a Lekérdezésoptimalizáló tippeken keresztül adhatja meg, például ROWLOCK
, PAGLOCK
vagy TABLOCK
. Ha PAGLOCK
-t vagy TABLOCK
-et használnak, az adatbázismotor azonnal felszabadít egy indexlapot, ha az összes sor törlődik erről az indexlapról. Ezzel szemben ROWLOCK
használatakor az összes törölt sor csak töröltként van megjelölve; később háttérfeladattal eltávolítja őket az indexlapról.
Optimalizált zárolással végzett törlési művelet
Ha töröl egy sort egy tranzakción belül, a sor- és oldalzárolások fokozatosan lesznek megszerezve és felszabadítva, és nem tartják fenn a tranzakció időtartamára. Például ezt a DELETE utasítást adva:
DELETE mytable
WHERE name = 'Bob';
A tranzakció időtartamára zárolást helyeznek az összes módosított sorra. A zárolás az Bob
értéknek megfelelő indexsorok TID-jén történik. Az optimalizált zárolással az oldal- és sorzárolások továbbra is megszerzésre kerülnek a frissítésekhez, de az egyes sorok frissítésekor minden egyes oldal- és sorzárolás azonnal feloldásra kerül. A TID-zárolás megakadályozza a sorok frissítését a tranzakció befejezéséig. A Bob
értékkel rendelkező sorokat beolvasni, beszúrni vagy törölni próbáló tranzakciók mindaddig le lesznek tiltva, amíg a törlési tranzakció véglegesítésre vagy visszaállításra nem kerül. (Az READ_COMMITTED_SNAPSHOT
adatbázis-beállítás és a SNAPSHOT
elkülönítési szint is lehetővé teszi az olvasást a korábban véglegesített állapot sorverziójából.)
Ellenkező esetben a törlési művelet zárolási mechanikája ugyanaz, mint az optimalizált zárolás nélkül.
Beszúrási művelet optimalizált zárolás nélkül
Egy tranzakción belüli sor beszúrásakor a sor tartományát nem kell zárolni a beszúrási műveletet végrehajtó tranzakció időtartamára. A beszúrt kulcsérték zárolása a tranzakció végéig elegendő a szerializálhatóság fenntartásához. Például, ha figyelembe vesszük ezt az INSERT utasítást:
INSERT mytable VALUES ('Dan');
A RangeI-N
mód kulcstartomány-zárolása a tartomány teszteléséhez David
névnek megfelelő indexsorra kerül. Ha a zárolás meg van adva, a Dan
értékkel rendelkező sor kerül beszúrásra, és egy kizárólagos (X
) zárolás kerül a beszúrt sorra. A RangeI-N
mód kulcstartományának zárolása csak a tartomány teszteléséhez szükséges, és nem tartható meg a beszúrási műveletet végrehajtó tranzakció időtartamára. Más tranzakciók beszúrhatnak vagy törölhetnek értékeket a beszúrt sor előtt vagy után a Dan
értékkel. A Dan
értékkel rendelkező sor olvasására, beszúrására vagy törlésére tett tranzakciók azonban mindaddig le lesznek tiltva, amíg a beszúrási tranzakció véglegesítésre vagy visszaállításra nem kerül.
Optimalizált zárolású beszúrási művelet
Egy tranzakción belüli sor beszúrásakor a sor tartományát nem kell zárolni a beszúrási műveletet végrehajtó tranzakció időtartamára. A sor- és oldalzárolások ritkán szerezhetők be, csak akkor, ha online index újraépítése folyamatban van, vagy ha egyidejű SERIALIZABLE
tranzakciók vannak folyamatban. Ha sor- és oldalzárolásokat szerez be, a rendszer gyorsan felszabadítja őket, és nem tartja meg a tranzakció időtartamára. A beszúrt kulcsérték kizárólagos TID-zárolásának elhelyezése a tranzakció végéig elegendő a szerializálhatóság fenntartásához. Például tekintsük ezt a INSERT
utasítást:
INSERT mytable VALUES ('Dan');
Optimalizált zárolás esetén a RangeI-N
zárolás csak akkor kerül megszerzésre, ha a példányban legalább egy tranzakció a SERIALIZABLE
elkülönítési szintet használja. A RangeI-N
mód kulcstartomány-zárolása a tartomány teszteléséhez David
névnek megfelelő indexsorra kerül. Ha a zárolás meg van adva, a Dan
értékkel rendelkező sor kerül beszúrásra, és egy kizárólagos (X
) zárolás kerül a beszúrt sorra. A RangeI-N
mód kulcstartományának zárolása csak a tartomány teszteléséhez szükséges, és nem tartható meg a beszúrási műveletet végrehajtó tranzakció időtartamára. Más tranzakciók beszúrhatnak vagy törölhetnek értékeket a beszúrt sor előtt vagy után a Dan
értékkel. A Dan
értékkel rendelkező sor olvasására, beszúrására vagy törlésére tett tranzakciók azonban mindaddig le lesznek tiltva, amíg a beszúrási tranzakció véglegesítésre vagy visszaállításra nem kerül.
Zárolási eszkaláció
A zárolás eszkalációja a számos finom szemcsés zár kevesebb durva szemcsés zárakba alakításának folyamata, ami csökkenti a rendszer terhelését, miközben növeli a párhuzamos feldolgozás miatti versengés valószínűségét.
A zárolás eszkalációjának működése attól függően változik, hogy engedélyezve van-e optimalizált zárolási.
Zárolás eszkalációja optimalizált zárolás nélkül
Mivel az adatbázismotor alacsony szintű zárolásokat szerez be, szándékzárakat is elhelyez az alacsonyabb szintű objektumokat tartalmazó objektumokon:
- Sorok vagy indexkulcstartományok zárolásakor az adatbázismotor szándékzárolást helyez el a sorokat vagy kulcsokat tartalmazó oldalakon.
- Oldalak zárolásakor az adatbázismotor szándékzárolást helyez el a lapokat tartalmazó magasabb szintű objektumokon. Az objektum szándékzárolása mellett a szándéklap zárolását is kérni kell a következő objektumokon:
- Nem klaszteres indexek levélszintű oldalai
- Fürtözött indexek adatoldalai
- Halom adatoldalak
Az adatbázismotor ugyanannak az utasításnak a sor- és oldalzárolását is elvégezheti a zárolások számának minimalizálása és a zárolás eszkalálásának valószínűségének csökkentése érdekében. Az adatbázismotor például elhelyezhet lapzárolásokat egy nem fürtözött indexen (ha az index csomópontjában elegendő egybefüggő kulcs van kiválasztva a lekérdezés teljesítéséhez), és sorzárolásokat a fürtözött indexen vagy a halmon.
A zárolások eszkalálásához az adatbázismotor megkísérli módosítani a táblán lévő szándékzárat a megfelelő teljes zárolásra, például egy szándék-kizárólagos (IX
) zárolást egy kizárólagos (X
) zárolásra, vagy egy szándékmegosztási (IS
) zárolást egy megosztott (S
) zárolásra. Ha a zárolás eszkalálási kísérlete sikeres, és a teljes táblazárolás be van szerezve, akkor a halom vagy index tranzakciója által tárolt összes HoBT-, lap- (PAGE
) vagy sorszintű (RID
, KEY
) zárolás felszabadul. Ha a teljes zárolás nem szerezhető be, akkor nem történik zároláseszkaláció, és az adatbázismotor továbbra is sor-, kulcs- vagy oldalzárolásokat szerez be.
Az adatbázismotor nem eszkalálja a sor- vagy kulcstartomány-zárolásokat az oldalzárakra, hanem közvetlenül táblázatzárakká eszkalálja őket. Hasonlóképpen, az oldalzárolások mindig eszkalálódnak a táblazárakra. A particionált táblák zárolása a társított partíció HoBT-szintjére eszkalálható a táblazárolás helyett. A HoBT-szintű zárolás nem feltétlenül zárolja a partícióhoz igazított HoBT-eket.
Jegyzet
A HoBT-szintű zárolások általában növelik az egyidejűséget, de holtpontot jelenthetnek, ha a különböző partíciókat zároló tranzakciók mindegyike ki szeretné bontani a kizárólagos zárolásokat a többi partícióra. Ritkán előfordulhat, hogy TABLE
zárolási részletesség jobb teljesítményt nyújt.
Ha a zárolás eszkalálási kísérlete meghiúsul az egyidejű tranzakciók által birtokolt, ütköző zárolások miatt, az adatbázismotor újrapróbálkozza a zárolás eszkalálását a tranzakció által beszerzett további 1250 zárolás esetében.
Minden eszkalációs esemény elsősorban egyetlen Transact-SQL utasítás szintjén működik. Az esemény indításakor az adatbázismotor megpróbálja eszkalálni az aktuális tranzakció által birtokolt összes zárolást az aktív utasítás által hivatkozott táblákban, feltéve hogy az megfelel az eszkalációs küszöbérték követelményeinek. Ha az eszkalációs esemény azelőtt kezdődik, hogy az utasítás elér egy táblázatot, a rendszer nem kísérli meg a táblán lévő zárolások eszkalálását. Ha a zárolás eszkalálása sikeres, a tranzakció által az előző utasításban beszerzett és az esemény indításakor még megtartott zárolások eszkalálódnak, ha a táblára az aktuális utasítás hivatkozik, és szerepel az eszkalációs eseményben.
Tegyük fel például, hogy egy munkamenet végrehajtja ezeket a műveleteket:
- Tranzakciót indít el.
- Frissítések
TableA
. Ez a(z)TableA
-ban kizárólagos sorzárolásokat hoz létre, amelyek a tranzakció befejezéséig vannak tartva. - Frissítések
TableB
. Ez a(z)TableB
-ban kizárólagos sorzárolásokat hoz létre, amelyek a tranzakció befejezéséig vannak tartva. - Végrehajt egy
SELECT
-t, amely aTableA
-et csatlakoztatja aTableC
-höz. A lekérdezés-végrehajtási terv szerint a sorokat aTableA
-ból kell lekérni, mielőtt a sorokat aTableC
-ből lekérjük. - A
SELECT
utasítás zárolási eszkalációt indít el, miközben sorokat kér le aTableA
-től, és mielőtt hozzáférne aTableC
-höz.
Ha a zárolás eszkalálása sikeres, csak a munkamenet által a TableA
tartott zárolások eszkalálódnak. Ebbe beletartoznak a SELECT
utasításból származó megosztott zárolások és az előző UPDATE
utasítás kizárólagos zárolásai is. Bár csak az a zárolás kerül figyelembe vételre, amelyet a munkamenet a TableA
-ban az SELECT
utasításhoz megszerzett annak eldöntéséhez, hogy szükséges-e a zárolás eszkalálása, amint az eszkalálás sikeres, a munkamenet által a TableA
-ben tartott összes zárolás a táblán egy kizárólagos zárolásra van eszkalálva, és a TableA
minden más, kisebb részletességű zárolása, beleértve a szándékzárakat is, fel van oldva.
A rendszer nem próbálja meg eszkalálni a(z) TableB
zárolásait, mert az TableB
utasításban nem volt aktív hivatkozás a(z) SELECT
-re. Hasonlóképpen nem történik kísérlet a zárolások eszkalálására TableC
, amelyek nem kerülnek eszkalálásra, mert még nem fértek hozzá, amikor az eszkaláció történt.
Zárolási eszkalálás optimalizált zárolással.
Az optimalizált zárolás segít csökkenteni a zárolási memóriát, mivel a tranzakció időtartama alatt nagyon kevés zárolás van tárolva. Mivel az adatbázismotor sor- és oldalzárolásokat szerez be, a zárolás eszkalálása hasonlóan, de sokkal ritkábban fordulhat elő. Az optimalizált zárolás általában sikeresen elkerüli a zárolások eszkalálódását, csökkentve a zárolások számát és a szükséges zárolási memória mennyiségét.
Ha az optimalizált zárolás engedélyezve van, és az alapértelmezett READ COMMITTED
elkülönítési szinten az adatbázismotor a sor módosítása után feloldja a sor- és oldalzárolásokat. A tranzakció időtartama alatt nem tart sor- és oldalzárolásokat, kivéve egyetlen tranzakcióazonosító (TID) zárolást. Ez csökkenti a zárolás eszkalálásának valószínűségét.
Eszkalációs küszöbértékek zárolása
A zárolás eszkalációja akkor aktiválódik, ha a zárolás eszkalációja nincs letiltva a táblában az ALTER TABLE SET LOCK_ESCALATION
beállítással, és ha a következő feltételek valamelyike létezik:
- Egyetlen Transact-SQL utasítás legalább 5000 zárolást szerez be egyetlen nem particionált táblán vagy indexen.
- Egyetlen Transact-SQL utasítás legalább 5000 zárolást szerez be egy particionált tábla egyetlen partícióján, és a
ALTER TABLE SET LOCK_ESCALATION
beállítás automatikusra van állítva. - Az adatbázismotor egy példányában a zárolások száma meghaladja a memória- vagy konfigurációs küszöbértékeket.
Ha a zárolások zárolási ütközések miatt nem eszkalálhatók, az adatbázismotor rendszeresen aktiválja a zárolás eszkalálását minden 1250 új zárolásnál.
Eszkalációs küszöbérték egy Transact-SQL utasításhoz
Amikor az adatbázismotor minden 1250 újonnan beszerzett zárolásnál ellenőrzi a lehetséges eszkalációkat, akkor és csak akkor fordul elő zároláseszkaláció, ha egy Transact-SQL utasítás legalább 5000 zárolást szerzett be egy tábla egyetlen hivatkozásán. A zárolás eszkalálása akkor aktiválódik, ha egy Transact-SQL utasítás legalább 5000 zárolást szerez be egy tábla egyetlen hivatkozásán. A zároláseszkaláció például nem aktiválódik, ha egy utasítás 3000 zárolást szerez be egy indexben, és 3000 zárolást ugyanazon tábla egy másik indexében. Hasonlóképpen, a zároláseszkaláció nem aktiválódik, ha egy utasítás önillesztést tartalmaz egy táblán, és a táblára mutató minden hivatkozás csak 3000 zárolást szerez be a táblában.
A zárolás eszkalálása csak azoknál a tábláknál történik, amelyek az eszkaláció aktiválásakor lettek elérve. Tegyük fel, hogy egyetlen SELECT
utasítás olyan illesztés, amely három táblához fér hozzá ebben a sorrendben: TableA
, TableB
és TableC
. A lekérdezés 3000 sorzárat foglal le a TableA
fürtözött indexben, és legalább 5000 sorzárat a TableB
fürtözött indexben, de a TableC
-hez még nem fér hozzá. Amikor az adatbázismotor észleli, hogy az utasítás legalább 5000 sorzárat szerzett be TableB
-n, megpróbálja eszkalálni az aktuális tranzakció összes zárolását a TableB
-en. Emellett megpróbálja eszkalálni az aktuális tranzakció által birtokolt összes zárolást a TableA
, de mivel a TableA
zárolásainak száma kevesebb, mint 5000, az eszkaláció nem fog sikerülni. A rendszer nem kíséreli meg a zárolás eszkalálását TableC
, mert az eszkaláció bekövetkezésekor még nem fért hozzá.
Az adatbázismotor egy példányának eszkalációs küszöbértéke
Amikor a zárolások száma nagyobb, mint a zárolás eszkalálásának memóriaküszöbe, az adatbázismotor aktiválja a zárolás eszkalálását. A memória küszöbértéke a zárak konfigurációs beállításától függ:
Ha a
locks
beállítás alapértelmezett értéke 0, akkor a zárolás eszkalációs küszöbértéke akkor éri el, ha a zárolási objektumok által használt memória az adatbázismotor által használt memória 24 százaléka, kivéve az AWE memóriát. A zárolások ábrázolására használt adatstruktúra körülbelül 100 bájt hosszú. Ez a küszöbérték dinamikus, mert az adatbázismotor dinamikusan szerez be és szabadít fel memóriát a változó számítási feladatokhoz való alkalmazkodáshoz.Ha a
locks
beállítás értéke nem 0, akkor a zárolás eszkalációs küszöbértéke a zárolási beállítás értékének 40 százaléka (vagy kisebb, ha memóriaterhelés van).
Az adatbázismotor bármilyen aktív utasítást választhat bármely munkamenetből az eszkaláláshoz, és minden 1250 új zárolás esetén az eszkalálási utasításokat választja, amíg a példányban használt zárolási memória a küszöbérték felett marad.
Vegyes zárolási típusok eszkalációja
Zárolás eszkalációja esetén a halomhoz vagy indexhez kiválasztott zár elég erős ahhoz, hogy megfeleljen a legkorlátozóbb alsó szintű zár követelményeinek.
Tegyük fel, hogy például van egy munkamenet:
- Tranzakciót indít el.
- Fürtözött indexet tartalmazó táblázat frissítése.
- Egy
SELECT
utasítást ad ki, amely ugyanarra a táblára hivatkozik.
A UPDATE
utasítás a következő zárolásokat szerzi be:
- Az exkluzív (
X
) zárolja a frissített adatsorokat. - A kizárólagos szándék (
IX
) zárolja azokat a sorokat tartalmazó fürtözött indexoldalakat. - Egy
IX
típusú zár a fürtözött indexen és egy másik a táblán.
A SELECT
utasítás a következő zárolásokat szerzi be:
- A megosztott (
S
) zárolja az összes beolvasott adatsort, kivéve, ha a sort márX
zárolás védi aUPDATE
utasításból. - A szándékmegosztás (
IS
) zárolja az összes olyan fürtözött indexoldalt, amely ezeket a sorokat tartalmazza, kivéve, ha a lapot márIX
zárolás védi. - Nincs zárolás a fürtözött indexen vagy táblán, mert már
IX
zárolások védik őket.
Ha a SELECT
utasítás elegendő zárolást szerez be a zárolás eszkalálásának aktiválásához, és az eszkaláció sikeres, a IX
zárolás a táblán X
zárolássá alakul, és az összes sor-, oldal- és indexzár felszabadul. A frissítéseket és olvasásokat a X
zárolás védi a táblán.
A zárolás és a zárolás eszkalálásának csökkentése
A legtöbb esetben az adatbázismotor a legjobb teljesítményt nyújtja az alapértelmezett zárolási és zárolási eszkalációs beállításokkal való működés során.
Használja ki a optimalizált zárolás.
- optimalizált zárolási továbbfejlesztett tranzakciózárolási mechanizmust kínál, amely csökkenti a zárolási memóriahasználatot és az egyidejű tranzakciók blokkolását. A zárolás eszkalálása sokkal kisebb valószínűséggel fordul elő, ha az optimalizált zárolás engedélyezve van.
- Kerülje a tábla tippek használatát az optimalizált zárolással. A táblázatos tippek csökkenthetik az optimalizált zárolás hatékonyságát.
- Engedélyezze az adatbázis READ_COMMITTED_SNAPSHOT beállítását az optimalizált zárolás leghasznosabb kihasználásához. Ez az alapértelmezett az Azure SQL Database-ben.
- Az optimalizált zároláshoz engedélyezni kell gyorsított adatbázis-helyreállítást (ADR) az adatbázisban.
Ha az adatbázismotor egy példánya sok zárolást hoz létre, és gyakran eszkalálódik a zárolás, fontolja meg a zárolás mennyiségének csökkentését az alábbi stratégiákkal:
Olyan elkülönítési szintet használjon, amely nem hoz létre megosztott zárolásokat olvasási műveletekhez:
- A
READ COMMITTED
izolációs szint van érvényben, ha aREAD_COMMITTED_SNAPSHOT
adatbázis opcióON
. -
SNAPSHOT
elkülönítési szint. -
READ UNCOMMITTED
elkülönítési szint. Ez csak olyan rendszerekhez használható, amelyek piszkos olvasással működnek.
- A
A
PAGLOCK
vagyTABLOCK
táblázat tippjeinek használatával az adatbázismotor az alacsony szintű zárolások helyett lap-, halom- vagy indexzárolásokat használhat. Ennek a lehetőségnek a használata azonban növeli azokat a problémákat, amikor a felhasználók blokkolják, hogy más felhasználók megpróbálják elérni ugyanazokat az adatokat, és ne használják több egyidejű felhasználóval rendelkező rendszerekben.Ha az optimalizált zárolás nem érhető el, particionált táblák esetén a
LOCK_ESCALATION
beállításával eszkalálhatja a zárolásokat a partícióra a tábla helyett, vagy letilthatja a táblák zárolásának eszkalálását.Bontsa fel a nagy kötegműveleteket több kisebb műveletre. Tegyük fel például, hogy a következő lekérdezést futtatva több százezer régi sort távolított el egy audittáblából, majd megállapította, hogy ez olyan zároláseszkalációt okozott, amely letiltotta a többi felhasználót:
DELETE FROM LogMessages WHERE LogDate < '2024-09-26'
Ha egyszerre néhány százat távolít el ezekből a sorokból, jelentősen csökkentheti a tranzakciónként felhalmozódó zárolások számát, és megakadályozhatja a zárolások eszkalálását. Például:
DECLARE @DeletedRows int; WHILE @DeletedRows IS NULL OR @DeletedRows > 0 BEGIN DELETE TOP (500) FROM LogMessages WHERE LogDate < '2024-09-26' SELECT @DeletedRows = @@ROWCOUNT; END;
A lekérdezés zárolási lábnyomának csökkentése a lekérdezés lehető leghatékonyabbá tételével. A nagy méretű pásztázások vagy a kulcskeresések nagy száma növelheti a zárolás eszkalációjának esélyét; emellett ez növeli a holtpontok esélyét, és általában hátrányosan hat az egyidejűségre és a teljesítményre. Miután megtalálta a zárolás eszkalációját okozó lekérdezést, keressen lehetőségeket új indexek létrehozására, vagy adjon hozzá oszlopokat egy meglévő indexhez, hogy eltávolítsa a teljes index- vagy táblavizsgálatokat, és maximalizálja az indexkeresések hatékonyságát. Fontolja meg a adatbázismotor finomhangolási tanácsadójának használatát a lekérdezés automatikus indexelemzéséhez. További információ: Oktatóanyag: Database Engine Tuning Advisor. Ennek az optimalizálásnak az egyik célja, hogy az indexek a lehető legkevesebb sort adjanak vissza a kulcskeresések költségének minimalizálása érdekében (maximalizálva az adott lekérdezés indexének szelektivitását). Ha az adatbázismotor becslése szerint egy kulcskeresési logikai operátor több sort is visszaadhat, előfordulhat, hogy a keresés végrehajtásához előzetes optimalizálás szükséges. Ha az adatbázismotor előbetöltést használ a kereséshez, a lekérdezés egy részének tranzakcióelkülönítési szintjét
REPEATABLE READ
-ra kell emelni. Ez azt jelenti, hogy ami aSELECT
utasításhoz hasonlít aREAD COMMITTED
elkülönítési szinten, sok ezer kulcs-zárolást szerezhet be (mind a fürtözött indexen, mind egy nem fürtözött indexen), ami ahhoz vezethet, hogy az ilyen lekérdezés túllépi a zárolási eszkaláció küszöbértékeit. Ez különösen akkor fontos, ha azt tapasztalja, hogy az eszkalált zárolás egy osztott táblazár, amely azonban általában nem szokott megjelenni az alapértelmezettREAD COMMITTED
elkülönítési szinten.Ha egy kulcskeresés az előzetes optimalizálással a zárolás eszkalációját okozza, érdemes lehet további oszlopokat hozzáadni az indexkeresésben megjelenő nemclustered indexhez, vagy az Indexkeresés logikai operátorhoz a lekérdezésterv kulcskeresési logikai operátora alatt. Létrehozhat egy lefedő indexet (olyan indexet, amely a lekérdezésben használt tábla összes oszlopát tartalmazza), vagy legalább egy olyan indexet, amely lefedi az illesztési feltételekhez használt oszlopokat, vagy a
WHERE
záradékban, ha aSELECT
oszloplistába mindent belefoglal, nem praktikus. A beágyazott hurkok összekapcsolása is használhatja az előcsatorna-optimalizálást, és ez ugyanazt a zárolási viselkedést okozza.A zárolás eszkalálása nem fordulhat elő, ha egy másik SPID jelenleg nem kompatibilis táblazárolást tartalmaz. A zárolás eszkalációja mindig egy táblazárolásra eszkalál, és soha nem az oldalzárakra. Ha egy zárolás eszkalálási kísérlete meghiúsul, mert egy másik SPID nem kompatibilis táblazárolással rendelkezik, a lekérdezés, amely megkísérelte az eszkalációt, nem blokkolódik a táblazárolásra való várakozás közben. Ehelyett továbbra is az eredeti, részletesebb szinten (sor, kulcs vagy oldal) szerez be zárolásokat, és rendszeres időközönként további eszkalációs kísérleteket végez. Ezért egy adott táblán a zárolás eszkalálásának megakadályozására szolgáló egyik módszer egy olyan zárolás beszerzése és tartása egy másik kapcsolaton, amely nem kompatibilis az eszkalált zárolástípussal. A kizárólagos szándékú (
IX
) zárolás a táblázat szintjén nem zárolja a sorokat vagy oldalakat, de továbbra sem kompatibilis az eszkalált megosztott (S
) vagy kizárólagos (X
) táblazárolással. Tegyük fel például, hogy olyan kötegelt feladatot kell futtatnia, amely amytable
táblában nagy számú sort módosít, és amely a zárolás eszkalációja miatt blokkolást okozott. Ha ez a feladat egy óránál rövidebb idő alatt fejeződik be, létrehozhat egy Transact-SQL feladatot, amely a következő kódot tartalmazza, és ütemezheti az új feladatot, hogy néhány perccel a kötegelt feladat kezdési időpontja előtt kezdődjön:BEGIN TRAN; SELECT * FROM mytable WITH (UPDLOCK, HOLDLOCK) WHERE 1 = 0; WAITFOR DELAY '1:00:00'; COMMIT TRAN;
Ez a lekérdezés egy órán keresztül egy
IX
zárolást szerez be és tart fennmytable
-en, amely megakadályozza a tábla zárolási szintjének eszkalálását ebben az időszakban. Ez a köteg nem módosít adatokat, és nem tilt le más lekérdezéseket (kivéve, ha a másik lekérdezés táblazárolást kényszerít ki aTABLOCK
tipptel, vagy ha a rendszergazda letiltotta az oldal- vagy sorzárolásokat egy indexenmytable
).Az 1211-es és az 1224-es nyomkövetési jelzőkkel is letilthatja az összes vagy néhány zárolási eszkalációt. Ezek a nyomkövetési jelzők azonban tiltják le az összes zárolási eszkalációt globálisan a teljes adatbázismotor-példány esetében. A zárolás eszkalációja hasznos célt szolgál az adatbázismotorban azáltal, hogy maximalizálja a lekérdezések hatékonyságát, amelyeket egyébként a több ezer zárolás beszerzésének és felszabadításának többletterhelése lassít. A zárolások eszkalálása emellett segít minimalizálni a szükséges memóriát a zárolások nyomon követéséhez. Az adatbázismotor által a zárolási struktúrákhoz dinamikusan lefoglalható memória véges, ezért ha letiltja a zárolás eszkalálását, és a zárolási memória elég nagy méretűre nő, a további zárolások lefoglalására tett kísérletek bármelyik lekérdezéshez sikertelenek lehetnek, és a következő hiba történik:
Error: 1204, Severity: 19, State: 1 The SQL Server cannot obtain a LOCK resource at this time. Rerun your statement when there are fewer active users or ask the system administrator to check the SQL Server lock and memory configuration.
Jegyzet
A MSSQLSERVER_1204 hiba bekövetkezésekor leállítja az aktuális utasítás feldolgozását, és az aktív tranzakció visszaállítását okozza. Maga a visszaállítás blokkolhatja a felhasználókat, vagy hosszú adatbázis-helyreállítási időt eredményezhet, ha újraindítja az adatbázis-szolgáltatást.
Jegyzet
A zárolási utasítás (például
ROWLOCK
) használata csak a kezdeti zárolás megszerzését módosítja. A zárolási utasítások nem akadályozzák a zárolás eszkalálódását.
Az SQL Server 2008 -tól kezdve (10.0.x) a zárolás eszkalációjának viselkedése megváltozott a LOCK_ESCALATION
táblabeállítás bevezetésével. További információért lásd az LOCK_ESCALATION
lehetőséget a ALTER TABLE.
Zárolás eszkalálásának monitorozása
Monitorozza a zárolás eszkalációját a lock_escalation
kiterjesztett esemény használatával, például az alábbi példában:
-- Session creates a histogram of the number of lock escalations per database
CREATE EVENT SESSION [Track_lock_escalation] ON SERVER
ADD EVENT sqlserver.lock_escalation
(
SET collect_database_name=1,collect_statement=1
ACTION(sqlserver.database_id,sqlserver.database_name,sqlserver.query_hash_signed,sqlserver.query_plan_hash_signed,sqlserver.sql_text,sqlserver.username)
)
ADD TARGET package0.histogram
(
SET source=N'sqlserver.database_id'
)
GO
Dinamikus zárolás
Az alacsony szintű zárolások, például a sorzárolások használata növeli az egyidejűséget azáltal, hogy csökkenti annak a valószínűségét, hogy két tranzakció egyszerre kér zárolást ugyanazon az adatrészen. Az alacsony szintű zárolások használata növeli a zárolások számát és a kezelésükhöz szükséges erőforrásokat is. A magas szintű táblázat- vagy oldalzárolások csökkentik a többletterhelést, de az egyidejűség csökkentése rovására.
Az adatbázismotor dinamikus zárolási stratégiát használ a leghatékonyabb zárolások meghatározásához. Az adatbázismotor automatikusan meghatározza, hogy mely zárolások a legmegfelelőbbek a lekérdezés végrehajtásakor a séma és a lekérdezés jellemzői alapján. A zárolás többletterhelésének csökkentése érdekében például az optimalizáló az indexek oldalzárolásait választhatja az indexvizsgálat során.
Partíciók zárolása
A nagy számítógépes rendszerek esetében a gyakran hivatkozott objektumok zárolása teljesítménybeli szűk keresztmetszetté válhat, mivel a zárolások beszerzése és felszabadítása a belső zárolási erőforrásokra helyezi a hangsúlyt. A zárolási particionálás javítja a zárolási teljesítményt azáltal, hogy egyetlen zárolási erőforrást több zárolási erőforrásra oszt. Ez a funkció csak a 16 vagy több logikai CPU-val rendelkező rendszerekhez érhető el, és automatikusan engedélyezve van, és nem tiltható le. Csak objektumzárak particionálhatók. Az altípussal rendelkező objektumzárak nincsenek particionálva. További információ: sys.dm_tran_locks (Transact-SQL).
A zárolás particionálásának ismertetése
A zárolási feladatok több megosztott erőforráshoz is hozzáférnek, amelyek közül kettő zárolási particionálással van optimalizálva:
Spinlock
Ez szabályozza a zárolási erőforráshoz, például egy sorhoz vagy egy táblához való hozzáférést.
Zárolásparticionálás nélkül egyetlen spinlock kezeli az egyetlen zárolási erőforrás összes zárolási kérését. A nagy mennyiségű tevékenységet tapasztaló rendszereken versengés léphet fel, amikor a zárolási kérések megvárják, amíg a spinlock elérhetővé válik. Ebben a helyzetben a zárak megszerzése szűk keresztmetszetté válhat, és negatív hatással lehet a teljesítményre.
Az egyetlen zárolási erőforrás versengésének csökkentése érdekében a zárolási particionálás egyetlen zárolási erőforrást több zárolási erőforrásra osztja fel, így a terhelés több spinlock között oszlik el.
memória
Ez a zárolási erőforrás-struktúrák tárolására szolgál.
A spinlock beszerzése után a zárolási struktúrák a memóriában lesznek tárolva, majd elérhetők és esetleg módosíthatók. A zárolási hozzáférés több erőforrás közötti elosztása segít kiküszöbölni a memóriablokkok cpu-k közötti átvitelének szükségességét, ami segít a teljesítmény javításában.
Zárolásparticionálás implementálása és monitorozása
A zárolási particionálás alapértelmezés szerint be van kapcsolva a 16 vagy több CPU-val rendelkező rendszerek esetében. Ha engedélyezve van a zárolási particionálás, a rendszer egy tájékoztató üzenetet rögzít az SQL Server hibanaplójában.
Particionált erőforrás zárolásainak beszerzésekor:
Csak
NL
,Sch-S
,IS
,IU
ésIX
zárolási módok érhetők el egyetlen partíción.A megosztott (
S
), az exkluzív (X
) és a más módokban lévő egyéb zárolásokat, kivéve aNL
,Sch-S
,IS
,IU
ésIX
módokat, a 0. partícióazonosítótól kezdve, a partícióazonosítók sorrendje szerint kell beszerezni. A particionált erőforrások zárolásai több memóriát használnak, mint a nem particionált erőforrások azonos módban lévő zárolásai, mivel az egyes partíciók gyakorlatilag külön zárolást alkotnak. A memória növekedését a partíciók száma határozza meg. Az SQL Server zárolási teljesítményszámlálói a particionált és nem particionált zárolások által használt memóriára vonatkozó információkat jelenítik meg.
A tranzakció indításakor a rendszer hozzárendel egy tranzakciót egy partícióhoz. A tranzakcióhoz a particionálásra használható összes zárolási kérés az adott tranzakcióhoz rendelt partíciót használja. Ezzel a módszerrel az ugyanazon objektum erőforrásainak zárolásához való hozzáférés különböző tranzakciók szerint oszlik el a különböző partíciók között.
A resource_lock_partition
Dinamikus felügyeleti nézet sys.dm_tran_locks
oszlopa megadja a zárolási partícióazonosítót egy zárolt particionált erőforráshoz. További információ: sys.dm_tran_locks (Transact-SQL).
Zárolási particionálással való munka
Az alábbi kód példák a zárolás particionálását szemléltetik. A példákban két tranzakciót hajtunk végre két különböző munkamenetben, hogy egy 16 CPU-val rendelkező számítógépes rendszeren megjelenítse a zárolás particionálási viselkedését.
Ezek a Transact-SQL utasítások az alábbi példákban használt tesztobjektumokat hoznak létre.
-- Create a test table.
CREATE TABLE TestTable
(
col1 int
);
GO
-- Create a clustered index on the table.
CREATE CLUSTERED INDEX ci_TestTable ON TestTable (col1);
GO
-- Populate the table.
INSERT INTO TestTable
VALUES (1);
GO
A példa
1. szekció:
A SELECT
utasítás végrehajtása tranzakcióval történik. A HOLDLOCK
zárolási jelölés miatt ez az utasítás egy megosztott szándék (IS
) zárolást szerez be és tart meg a táblán (erre az esetre a sor- és oldalzárolások figyelmen kívül maradnak). A IS
zárolás csak a tranzakcióhoz rendelt partíción lesz megszerezve. Ebben a példában azt feltételezzük, hogy a IS
zár megszerzése a 7-es partícióazonosítón történik.
-- Start a transaction.
BEGIN TRANSACTION;
-- This SELECT statement will acquire an IS lock on the table.
SELECT col1
FROM TestTable
WITH (HOLDLOCK);
2. szekció
A tranzakció elindul, és a tranzakció alatt futó SELECT
utasítás egy megosztott (S
) zárolást szerez be és őriz meg a táblán. A S
zárolás minden partíción be van szerezve, ami több táblazárolást eredményez, egy-egy partícióhoz. Egy 16 PROCESSZORos rendszerben például 16 S
zárolás lesz kiállítva a 0-15-ös zárolási partícióazonosítók között. Mivel a S
zárolás kompatibilis az 1. munkamenetben a tranzakció által a 7. partícióazonosítón tárolt IS
zárolással, a tranzakciók között nincs blokkolás.
BEGIN TRANSACTION;
SELECT col1
FROM TestTable
WITH (TABLOCK, HOLDLOCK);
1. szekció:
A következő SELECT
utasítás végrehajtása az 1. munkamenet alatt még aktív tranzakció alatt történik. A kizárólagos (X
) táblazár utasítás miatt a tranzakció megpróbál X
zárolást szerezni a táblán. A 2. munkamenetben a tranzakció által tartott S
zárolás azonban blokkolja a X
zárolást a 0 partícióazonosítónál.
SELECT col1
FROM TestTable
WITH (TABLOCKX);
B példa
1. szekció:
A SELECT
utasítás végrehajtása tranzakcióval történik. A HOLDLOCK
zárolási jelölés miatt ez az utasítás egy megosztott szándék (IS
) zárolást szerez be és tart meg a táblán (erre az esetre a sor- és oldalzárolások figyelmen kívül maradnak). A IS
zárolás csak a tranzakcióhoz rendelt partíción lesz megszerezve. Ebben a példában feltételezzük, hogy a IS
zárolás a 6- os partícióazonosítón van beolvasva.
-- Start a transaction.
BEGIN TRANSACTION;
-- This SELECT statement will acquire an IS lock on the table.
SELECT col1
FROM TestTable
WITH (HOLDLOCK);
2. szekció
A SELECT
utasítás végrehajtása tranzakcióval történik. A TABLOCKX
zárolási tipp miatt a tranzakció megpróbál kizárólagos (X
) zárolást szerezni a táblán. Ne feledje, hogy a X
zárolást minden olyan partícióra meg kell szerezni, amelynek azonosítója 0-val kezdődik. A X
zárolás az összes 0-5 partícióazonosítón be van szerezve, de a 6. partícióazonosítón beszerzett IS
zárolás blokkolja.
A 7-től 15-ig tartó partícióazonosítókon, amelyeket a X
zárolás még nem ért el, más tranzakciók továbbra is megszerezhetik a zárakat.
BEGIN TRANSACTION;
SELECT col1
FROM TestTable
WITH (TABLOCKX, HOLDLOCK);
Sorverzió-alapú elkülönítési szintek az adatbázismotorban
Az SQL Server 2005-től (9.x) az adatbázismotor egy meglévő tranzakcióelkülönítési szint implementációját kínálja, READ COMMITTED
, amely utasításszintű pillanatképet biztosít sorverziók használatával. Az adatbázismotor egy tranzakcióelkülönítési szintet is kínál, SNAPSHOT
, amely tranzakciószintű pillanatképet biztosít a sorverziók használatával is.
A sorverziózás az SQL Server általános keretrendszere, amely egy sor módosításakor vagy törlésekor egy másolási-írási mechanizmust hív meg. Ehhez a tranzakció futtatása közben a sor régi verziójának elérhetőnek kell lennie a korábbi tranzakciós konzisztens állapotot igénylő tranzakciókhoz. A sorverziók a következő funkciók implementálásához használhatók:
- Hozza létre a
inserted
ésdeleted
táblákat az eseményindítókban. Az eseményindító által módosított sorok verziószámozottak. Ide tartoznak az eseményindítót kezdeményező utasítás által módosított sorok, valamint az eseményindító által végrehajtott adatmódosítások. - Több aktív eredményhalmaz (MARS) támogatása. Ha egy MARS-munkamenet adatmódosítási utasítást (például
INSERT
,UPDATE
vagyDELETE
) ad ki egy aktív eredményhalmaz esetén, a módosítási utasítás által érintett sorok verziószámozottak lesznek. - Támogassa az indexműveleteket, amelyek megadják a
ONLINE
lehetőséget. - A sor verziószámozáson alapuló tranzakcióelkülönítési szintjeinek támogatása:
- A
READ COMMITTED
elkülönítési szint új implementációja, amely sorverziók alkalmazása révén biztosítja az utasításszintű olvasási konzisztenciát. - Egy új elkülönítési szint,
SNAPSHOT
, amely tranzakciószintű olvasási konzisztenciát biztosít.
- A
A sorverziók egy verziótárban vannak tárolva. Ha gyorsított adatbázis-helyreállítás (ADR) engedélyezve van egy adatbázisban, a verziótár az adatbázisban jön létre. Ellenkező esetben a verziótár a tempdb
adatbázisban jön létre.
Az adatbázisnak elegendő helytel kell rendelkeznie a verziótár számára. Ha a verziótár tempdb
van, és a tempdb
adatbázis megtelt, a frissítési műveletek leállnak, de továbbra is sikeresek lesznek, de az olvasási műveletek meghiúsulhatnak, mert nem létezik egy adott sorverzió, amely szükséges. Ez hatással van az olyan műveletekre, mint az eseményindítók, a MARS és az online indexelés.
Ha az ADR használata és a verziótár megtelt, az olvasási műveletek továbbra is sikeresek maradnak, de a verziót létrehozó írási műveletek, például UPDATE
és DELETE
sikertelenek lesznek.
INSERT
műveletek továbbra is sikeresek maradnak, ha az adatbázisnak elegendő hely áll rendelkezésre.
A READ COMMITTED
és SNAPSHOT
tranzakciók sorverziójának használata kétlépéses folyamat:
Állítsa be a
READ_COMMITTED_SNAPSHOT
vagyALLOW_SNAPSHOT_ISOLATION
adatbázis-beállításokat, vagy akár mindkettőtON
-re.Adja meg a megfelelő tranzakcióelkülönítési szintet egy alkalmazásban:
- Ha a
READ_COMMITTED_SNAPSHOT
adatbázis-beállításON
, aREAD COMMITTED
elkülönítési szintet beállító tranzakciók sorverziót használnak. - Ha a
ALLOW_SNAPSHOT_ISOLATION
adatbázis-beállításON
, a tranzakciók beállíthatják aSNAPSHOT
elkülönítési szintet.
- Ha a
Ha a READ_COMMITTED_SNAPSHOT
vagy ALLOW_SNAPSHOT_ISOLATION
adatbázis-beállítást ON
értékre állítják, az adatbázismotor tranzakciósorrend számot (XSN) rendel minden olyan tranzakcióhoz, amely sorverziók használatával módosítja az adatokat. A tranzakciók a BEGIN TRANSACTION
utasítás végrehajtásának időpontjában kezdődnek. A tranzakciósorozat száma azonban a BEGIN TRANSACTION
utasítás utáni első olvasási vagy írási művelettel kezdődik. A tranzakció sorozatszáma minden hozzárendeléskor eggyel növekszik.
Ha a READ_COMMITTED_SNAPSHOT
vagy ALLOW_SNAPSHOT_ISOLATION
adatbázis-beállítások ON
értékre vannak állítva, a logikai másolatok (verziók) megmaradnak az adatbázisban végrehajtott összes adatmódosítás esetében. Minden alkalommal, amikor egy adott tranzakció módosít egy sort, az adatbázismotor példánya a sor korábban véglegesített rendszerképének egy verzióját tárolja a verziótárban. Minden verzió a módosítást okozó tranzakció tranzakcióütemezési számával van megjelölve. A módosított sorok verziói egy összekapcsolt listával láncba vannak kötve. A legújabb sorértéket a rendszer mindig az aktuális adatbázisban tárolja, és a verziótár verziószámozott soraihoz láncolja.
Jegyzet
Nagy objektumok (LOB-k) módosításához a rendszer csak a módosított töredéket másolja a verziótárba.
A sorverziókat addig tárolják, amíg meg nem felelnek a sorverzióalapú elkülönítési szinteken futó tranzakciók követelményeinek. Az adatbázismotor nyomon követi a legkorábbi hasznos tranzakcióütemezési számot, és rendszeres időközönként törli az összes olyan sorverziót, amely a legkorábbi hasznos sorszámnál alacsonyabb tranzakcióütemezési számmal van megjelölve.
Ha mindkét adatbázis-beállítás OFF
van beállítva, csak az eseményindítók vagy MARS-munkamenetek által módosított, illetve az online indexelési műveletek által beolvasott sorok lesznek verziószámozottak. Ezek a sorverziók akkor jelennek meg, ha már nincs rá szükség. A háttérfolyamat eltávolítja az elavult sorverziókat.
Jegyzet
Rövid ideig futó tranzakciók esetén előfordulhat, hogy egy módosított sor egy verziója gyorsítótárazva lesz a pufferkészletben anélkül, hogy a verziótárba íródott. Ha a verziószámozott sor rövid élettartamú, a sor el lesz távolítva a pufferkészletből, és nem jár I/O-többletterheléssel.
Viselkedés adatok olvasásakor
Sor-verzióalapú izoláció alatt futó tranzakciók esetében az olvasási műveletek nem szereznek megosztott (S
) zárolásokat az éppen olvasott adatokon, ezért nem akadályozzák az adatokat módosító tranzakciókat. Emellett a zárolási erőforrások többletterhelése is minimálisra csökken, mivel a beszerzett zárolások száma csökken.
READ COMMITTED
sorverziós és SNAPSHOT
elkülönítéssel történő elkülönítés a verziószámozott adatok utasításszintű vagy tranzakciószintű olvasási konzisztenciáját biztosítja.
Minden lekérdezés, beleértve a sorverzióalapú elkülönítési szinteken futó tranzakciókat is, sémastabilitási zárakat (Sch-S
) szerez a fordítás és a végrehajtás során. Emiatt a lekérdezések le lesznek tiltva, ha egy egyidejű tranzakció sémamódosítási (Sch-M
) zárolást tartalmaz a táblán. Egy adatdefiníciós nyelv (DDL) művelet például Sch-M
zárolást szerez be, mielőtt módosítja a tábla sémaadatait. A tranzakciók, beleértve a sorverzióalapú elkülönítési szinten futó tranzakciókat is, le lesznek tiltva, amikor Sch-S
zárolást próbálnak beszerezni. Ezzel szemben egy Sch-S
zárolást tartalmazó lekérdezés blokkolja az egyidejű tranzakciót, amely megpróbál Sch-M
zárolást szerezni.
Amikor elindul egy SNAPSHOT
elkülönítési szintet használó tranzakció, az adatbázismotor példánya rögzíti az összes jelenleg aktív tranzakciót. Amikor a SNAPSHOT
tranzakció egy verzióláncot tartalmazó sort olvas be, az adatbázismotor követi a láncot, és lekéri azt a sort, amelyben a tranzakciósorozat száma:
A sorokat olvasó pillanatkép-tranzakció sorszámához legközelebbi, de annál alacsonyabb.
A pillanatkép-tranzakció indításakor aktív tranzakciók listájában nem szerepel.
Az SNAPSHOT
tranzakció által végrehajtott olvasási műveletek lekérik a SNAPSHOT
tranzakció indításakor véglegesített sorok utolsó verzióját. Ez tranzakciósan konzisztens pillanatképet biztosít az adatokról, ahogyan azok a tranzakció elején léteztek.
READ COMMITTED
sorverziót használó tranzakciók nagyjából ugyanúgy működnek. A különbség az, hogy a READ COMMITTED
tranzakció nem használja a saját tranzakcióütemezési számát a sorverziók kiválasztásakor. Minden egyes utasítás indításakor a READ COMMITTED
tranzakció beolvassa az adatbázismotor adott példányához kiadott legújabb tranzakcióütemezési számot. Ez az utasítás sorverzióinak kiválasztásához használt tranzakcióütemezési szám. Ez lehetővé teszi READ COMMITTED
tranzakciók számára, hogy az egyes utasítások elején létező adatok pillanatképét lássák.
Jegyzet
Annak ellenére, hogy READ COMMITTED
sorverziót használó tranzakciók tranzakciós konzisztens nézetet biztosítanak az adatokról utasításszinten, az ilyen típusú tranzakció által létrehozott vagy elért sorverziók mindaddig megmaradnak, amíg a tranzakció befejeződik.
Viselkedés az adatok módosításakor
Az adatírások viselkedése eltérő az optimalizált zárolás engedélyezésével és nélkül.
Adatok módosítása optimalizált zárolás nélkül
Egy sorverziót használó READ COMMITTED
tranzakcióban a frissítendő sorok kijelölése blokkolási vizsgálattal történik, ahol az adatértékek olvasása során egy frissítési (U
) zárolást szerez be az adatsoron. Ez ugyanaz, mint egy READ COMMITTED
tranzakció, amely nem használ sorverzió-kezelést. Ha az adatsor nem felel meg a frissítési feltételeknek, a rendszer felszabadítja a frissítési zárolást, és a következő sort zárolja és beolvasja.
A SNAPSHOT
elkülönítés alatt futó tranzakciók optimista megközelítést alkalmaznak az adatmódosításhoz azáltal, hogy zárolásokat szereznek be az adatokon, mielőtt a módosítást csak a korlátozások kényszerítése érdekében hajtják végre. Ellenkező esetben az adatokhoz csak akkor lesznek zárolások alkalmazva, amikor azokat módosítani kell. Amikor egy adatsor megfelel a frissítési feltételeknek, a SNAPSHOT
tranzakció ellenőrzi, hogy az adatsort nem módosította-e a SNAPSHOT
tranzakció elindítása után lekötött egyidejű tranzakció. Ha az adatsort a SNAPSHOT
tranzakción kívül módosították, frissítési ütközés lép fel, és a SNAPSHOT
tranzakció leáll. A frissítési ütközést az adatbázismotor kezeli, és nem lehet letiltani a frissítésütközés észlelését.
Jegyzet
Az SNAPSHOT
elkülönítés alatt futó frissítési műveletek belsőleg READ COMMITTED
elkülönítés alatt futnak, amikor a SNAPSHOT
tranzakció az alábbiak bármelyikéhez hozzáfér:
Egy idegenkulcs-korlátozással rendelkező tábla.
Egy tábla, amelyre egy másik tábla idegenkulcs-korlátozása hivatkozik.
Egy több táblára hivatkozó indexelt nézet.
A frissítési művelet azonban még ezekben a feltételekben is ellenőrzi, hogy az adatokat nem módosította-e egy másik tranzakció. Ha az adatokat egy másik tranzakció módosította, a SNAPSHOT
tranzakció frissítési ütközésbe ütközik, és leáll. Az alkalmazásnak kell kezelnie és újra próbálkoznia a frissítési ütközések esetén.
Adatok módosítása optimalizált zárolással
Ha engedélyezve van az optimalizált zárolás, és engedélyezve van az READ_COMMITTED_SNAPSHOT
(RCSI) adatbázis-beállítás, és az alapértelmezett READ COMMITTED
elkülönítési szint használatával az olvasók nem szereznek be semmilyen zárolást, az írók pedig rövid időtartamú, alacsony szintű zárolásokat szereznek be a tranzakció végén lejáró zárolások helyett.
Az RCSI engedélyezése az optimalizált zárolással a legnagyobb hatékonyság érdekében ajánlott. Ha szigorúbb elkülönítési szinteket (például REPEATABLE READ
vagy SERIALIZABLE
) használ, az adatbázismotor a tranzakció végéig sor- és oldalzárolásokat tart az olvasók és írók számára, ami megnöveli a memória blokkolását és zárolását.
Ha engedélyezve van az RCSI, és ha az alapértelmezett READ COMMITTED
elkülönítési szintet használja, az írók a sor legújabb véglegesített verziója alapján minősítik a predikátumban szereplő sorokat anélkül, hogy U
zárolásokat szereznek be. A lekérdezés csak akkor várakozik, ha a sor megfelel a feltételeknek, és van egy másik aktív írási tranzakció azon a soron vagy lapon. A legújabb véglegesített verzió alapján történő minősítés és a csak a minősített sorok zárolása csökkenti a blokkolást és növeli az egyidejűséget.
Ha az RCSI-vel frissítési ütközések észlelhetők, és az alapértelmezett READ COMMITTED
elkülönítési szinten, a rendszer automatikusan kezeli és újrapróbálkozza őket anélkül, hogy ez hatással lenne az ügyfél számítási feladataira.
Az optimalizált zárolás engedélyezésével és a SNAPSHOT
elkülönítési szint használatakor a frissítési ütközések viselkedése ugyanaz, mint az optimalizált zárolás nélkül. Az alkalmazásnak kell kezelnie és újra próbálkoznia a frissítési ütközések esetén.
Jegyzet
Az optimalizált zárolás minősítés utáni (LAQ) funkciójának viselkedésváltozásaival kapcsolatos további információkért lásd a lekérdezés viselkedésének változásait az optimalizált zárolással és az RCSI-vel a ésszámú pontokban.
A viselkedés összegzése
Az alábbi táblázat a sorverziós SNAPSHOT
és READ COMMITTED
elkülönítés közötti különbségeket foglalja össze.
Ingatlan |
READ COMMITTED izolációs szint sorverzió használatával |
SNAPSHOT elkülönítési szint |
---|---|---|
Az adatbázis beállításának ON kell lennie a szükséges támogatás engedélyezéséhez. |
READ_COMMITTED_SNAPSHOT |
ALLOW_SNAPSHOT_ISOLATION |
Hogyan kéri egy munkamenet a sor verziószámozásának adott típusát. | Használja az alapértelmezett READ COMMITTED elkülönítési szintet, vagy futtassa a SET TRANSACTION ISOLATION LEVEL utasítást a READ COMMITTED elkülönítési szint megadásához. Ez a tranzakció elindítása után is elvégezhető. |
A SET TRANSACTION ISOLATION LEVEL végrehajtására van szükség a SNAPSHOT elkülönítési szintjének megadásához a tranzakció megkezdése előtt. |
Az utasítások által beolvasott adatok verziója. | Minden adat, amelyet az egyes állítások kezdete előtt véglegesítettek. | Minden olyan adat, amelyet az egyes tranzakciók kezdete előtt véglegesítettek. |
A frissítések kezelése. |
Optimalizált zárolás nélkül: A sorverziókról a tényleges adatokra való visszaállítással kijelöli a frissítendő sorokat, és frissítési zárolásokat használ a kijelölt adatsorokon. Kizárólagos zárolásokat szerez be a módosítani kívánt tényleges adatsorokon. Nincs frissítésütközés észlelése. Optimalizált zárolás esetén: a sorok az utolsó véglegesített verzió alapján anélkül vannak kiválasztva, hogy bármilyen zárolás megszerzésére kerülne sor. Ha a sorok megfelelnek a frissítésnek, a rendszer kizárólagos sor- vagy oldalzárolásokat szerez be. Frissítési ütközések észlelése esetén a rendszer automatikusan kezeli és újrapróbálkozza őket. |
A sorverziók használatával kijelöli a frissítendő sorokat. Megpróbál kizárólagos zárolást szerezni a módosítani kívánt adatsoron, és ha az adatokat egy másik tranzakció módosította, frissítési ütközés lép fel, és a pillanatkép-tranzakció leáll. |
Ütközés-detektálás frissítése |
Optimalizált zárolás nélkül: Nincs. Optimalizált zárolással: Frissítési ütközések észlelése esetén a rendszer automatikusan kezeli és újrapróbálkozza őket. |
Integrált támogatás. Nem tiltható le. |
Sorverziós erőforrás-használat
A sorverzió-keretrendszer a következő adatbázismotor-funkciókat támogatja:
- Eseményindítók
- Több aktív eredményhalmaz (MARS)
- Online indexelés
A sorverziózási keretrendszer a következő sorverzió-alapú tranzakcióelkülönítési szinteket is támogatja:
- Ha a
READ_COMMITTED_SNAPSHOT
adatbázis beállításaON
, aREAD_COMMITTED
tranzakciók utasításszintű olvasási konzisztenciát biztosítanak, a sorverziók használatával. - Ha a
ALLOW_SNAPSHOT_ISOLATION
adatbázis opcióON
értékre van állítva, aSNAPSHOT
tranzakciók sorverziók használatával biztosítanak tranzakciószintű olvasási konzisztenciát.
A sorverzió-alapú elkülönítési szintek csökkentik a tranzakció által megszerzett zárolások számát azáltal, hogy az olvasási műveleteknél nem használnak megosztott zárolásokat. Ez növeli a rendszer teljesítményét a zárolások kezeléséhez használt erőforrások csökkentésével. A teljesítmény is növelhető azáltal, hogy csökkenti azt a számot, amikor egy tranzakciót más tranzakciók által beszerzett zárolások blokkolnak.
A sorverzió-alapú elkülönítési szintek növelik az adatmódosításokhoz szükséges erőforrásokat. Ezeknek a beállításoknak a engedélyezésével az adatbázis összes adatmódosítása verziószámozásra kerül. A módosítás előtti adatok másolata akkor is a verziótárban lesz tárolva, ha nincsenek aktív tranzakciók sorverzióalapú elkülönítéssel. A módosítás utáni adatok a verziótárban lévő verziójú adatokra mutató mutatót tartalmaznak. Nagy objektumok esetén a rendszer csak a módosított objektum egy részét tárolja a verziótárban.
A tempdb-ben használt terület
Az adatbázismotor minden példánya esetében a verziótárnak elegendő helytel kell rendelkeznie a sorverziók tárolásához. Az adatbázis-rendszergazdának biztosítania kell, hogy a tempdb
és a többi adatbázis (ha az ADR engedélyezve van) elegendő helyet kapjon a verziótárhoz. A verziótáraknak két típusa van:
- Az online index építési verzió tár használatos az online index építésekhez.
- A közös verziótár minden más adatmódosítási művelethez használható.
A sorverziókat mindaddig tárolni kell, amíg egy aktív tranzakciónak hozzá kell férnie. Időnként egy háttérszál eltávolítja a már nem szükséges sorverziókat, és helyet szabadít fel a verziótárban. A hosszú ideig futó tranzakció megakadályozza, hogy a verziótárban lévő tárhely felszabaduljon, ha megfelel az alábbi feltételek bármelyikének:
- Soronkénti verziózás alapú elkülönítést használ.
- Triggereket, MARS- vagy online indexépítési műveleteket használ.
- Sorverziókat hoz létre.
Jegyzet
Amikor egy tranzakcióban eseményindítót hív meg, az eseményindító által létrehozott sorverziók a tranzakció végéig megmaradnak, annak ellenére, hogy a sorverziókra már nincs szükség az eseményindító befejeződése után. A READ COMMITTED
tranzakciókra is vonatkozik, amelyek sorverziót használnak. Ilyen típusú tranzakció esetén az adatbázis tranzakciós konzisztens nézetére csak a tranzakció minden egyes utasításához van szükség. Ez azt jelenti, hogy a tranzakcióban lévő utasításhoz létrehozott sorverziókra már nincs szükség az utasítás befejezése után. A tranzakció egyes utasításai által létrehozott sorverziók azonban mindaddig megmaradnak, amíg a tranzakció befejeződik.
Ha a verziótár tempdb
-ben van, és tempdb
elfogy a hely, az adatbázismotor a verziótárolókat zsugorítására kényszeríti. A zsugorítási folyamat során a leghosszabb ideig futó tranzakciók, amelyek még nem generáltak sorverziókat, áldozatokként lesznek megjelölve. A rendszer egy 3967-et jelző üzenetet hoz létre az egyes áldozati tranzakciók hibanaplójában. Ha egy tranzakció áldozatként van megjelölve, a továbbiakban nem tudja beolvasni a sorverziókat a verziótárban. Amikor megpróbálja elolvasni a sorverziókat, a 3966-os üzenet jön létre, és a tranzakció vissza lesz állítva. Ha a zsugorítási folyamat sikeres, hely válik elérhetővé a tempdb
-ban. Ellenkező esetben tempdb
elfogy a hely, és a következők történnek:
Az írási műveletek továbbra is futnak, de nem hoznak létre verziókat. A hibanaplóban megjelenik egy információs üzenet (3959), de az adatokat író tranzakcióra nincs hatással.
Azok a tranzakciók, amelyek a
tempdb
teljes visszaállítás miatt nem létrehozott sorverziókat próbálják elérni, a 3958-as hibával érnek véget.
Adatsorokban használt terület
Az egyes adatbázissorok legfeljebb 14 bájtot használhatnak a sor végén a sor verziószámozási információihoz. A sor verziószámozási információi a verziót véglegesítő tranzakció tranzakcióütemezési számát és a verziószámozott sorra mutató mutatót tartalmazzák. Ezt a 14 bájtot a rendszer a sor első módosításakor vagy új sor beszúrásakor adja hozzá a következő feltételek bármelyike mellett:
- A(z)
READ_COMMITTED_SNAPSHOT
vagyALLOW_SNAPSHOT_ISOLATION
opciókON
-re vannak állítva. - A tábla eseményindítóval rendelkezik.
- Több aktív eredményhalmaz (MARS) van használatban.
- Az online indexépítési műveletek jelenleg a táblán futnak.
- A gyorsított adatbázis-helyreállítás (ADR) engedélyezve van.
Ezeket a 14 bájtokat a rendszer eltávolítja az adatbázis sorából az első alkalommal, amikor a sor az alábbi feltételek teljesülése esetén módosul:
- A
READ_COMMITTED_SNAPSHOT
ésALLOW_SNAPSHOT_ISOLATION
beállításokOFF
-re vannak beállítva. - Az eseményindító már nem létezik az asztalon.
- A MARS nincs használatban.
- Az online index buildelési műveletei jelenleg nem futnak.
- A gyorsított adatbázis-helyreállítás (ADR) le van tiltva.
Ha a sor verziószámozási funkcióinak bármelyikét használja, előfordulhat, hogy további lemezterületet kell lefoglalnia az adatbázis számára az adatbázis soronkénti 14 bájtos elhelyezéséhez. A sor verziószámozási adatainak hozzáadása indexoldalak felosztását vagy új adatoldal lefoglalását okozhatja, ha nincs elegendő szabad hely az aktuális oldalon. Ha például az átlagos sorhossz 100 bájt, a további 14 bájt miatt egy meglévő tábla akár 14%-ra is nőhet.
A kitöltési tényező csökkentése segíthet megelőzni vagy csökkenteni az indexlapok töredezettségét. A tábla vagy nézet adatainak és indexeinek aktuális lapsűrűségi információinak megtekintéséhez használhatja a sys.dm_db_index_physical_stats.
Az állandó verziótár (PVS) által használt terület
Ha az ADR engedélyezve van, a sorverziók az állandó verziótárban (PVS) tárolhatók a módosítás előtti sor méretétől függően:
- Ha a méret kicsi, a rendszer a teljes régi sorverziót a módosított sor részeként tárolja.
- Ha a méret köztes, a régi és a módosított sor közötti különbség a módosított sor részeként lesz tárolva. A különbség úgy van kialakítva, hogy az adatbázismotor szükség esetén rekonstruálja a teljes régi sorverziót.
- Ha a méret nagy, a teljes régi sorverzió egy külön belső táblában lesz tárolva.
Az első két metódust egymás utáni verziótárolónak nevezzük. Az utolsó metódus neve soron kívüli verziótároló. Ha a soron belüli verziókra már nincs szükség, a rendszer eltávolítja őket, hogy helyet szabadítson fel a lapokon. Hasonlóképpen, a belső táblázat azon lapjait, amelyekben már nincs szükség soron kívüli verziókra, a verziótisztító eltávolítja.
A sorverziók sor részeként történő tárolása optimalizálja az adatlekérést olyan tranzakciók alapján, amelyeknek sorverziókat kell olvasniuk. Ha egy verzió egymás után van tárolva, nem szükséges külön olvasni egy soron kívüli PVS-lapot.
A sys.dm_db_index_physical_stats DMV egy index partíciójához a sorban és soron kívül tárolt verziók számát és típusát adja meg. A sorban tárolt verzióadatok teljes méretét a total_inrow_version_payload_size_in_bytes
oszlopban jelentik.
A soron kívüli verzió tárterületének méretét a persistent_version_store_size_kb
DMV oszlopában jelenti.
Nagy objektumokban használt terület
Az adatbázismotor számos olyan adattípust támogat, amelyek legfeljebb 2 gigabájt (GB) hosszúságú nagy sztringeket tartalmazhatnak, például: nvarchar(max)
, varchar(max)
, varbinary(max)
, ntext
, text
és image
. Az ilyen adattípusok használatával tárolt nagyméretű adatok adattöredékek sorozatában vannak tárolva, amelyek az adatsorhoz vannak csatolva. A sorok verziószámozási adatait minden olyan töredékben tárolják, amely ezeket a nagy karakterláncokat tárolja. Az adattöredékek egy táblázat nagy objektumainak dedikált lapkészletében vannak tárolva.
Amikor új nagy értékeket ad hozzá egy adatbázishoz, azok töredékenként legfeljebb 8040 bájtnyi adattal lesznek lefoglalva. Az adatbázismotor korábbi verziói legfeljebb 8080 bájtnyi ntext
, text
vagy image
adatot tárolnak töredékenként.
A meglévő ntext
, text
és image
nagyméretű objektumadatok (LOB) nem frissülnek, így helyet ad a sor verziószámozási információinak, ha egy adatbázist az SQL Server egy korábbi verziójáról frissít az SQL Serverre. A LOB-adatok első módosításakor azonban dinamikusan frissül, hogy lehetővé tegye a verziószámozási adatok tárolását. Ez akkor is megtörténik, ha a sorverziók nem kerülnek létrehozásra. A LOB-adatok frissítése után a töredékenként tárolt bájtok maximális száma 8080 bájtról 8040 bájtra csökken. A frissítési folyamat egyenértékű a LOB érték törlésével és ugyanazon érték újbóli beszúrásával. A LOB-adatok akkor is frissülnek, ha csak 1 bájt van módosítva. Ez egy egyszeri művelet minden ntext
, text
vagy image
oszlophoz, de minden művelet nagy mennyiségű oldalfoglalást és I/O-tevékenységet generálhat a LOB-adatok méretétől függően. Nagy mennyiségű naplózási tevékenységet is generálhat, ha a módosítás teljes mértékben naplózva van.
WRITETEXT
és UPDATETEXT
műveleteket a rendszer minimálisan naplózza, ha az adatbázis-helyreállítási modell nincs FULL értékre állítva.
A követelménynek megfelelően elegendő lemezterületet kell lefoglalni.
A sorverziók és a verziótár figyelése
A sorverziók, a verziótár és a pillanatképek elkülönítési folyamatainak teljesítményének és problémáinak figyeléséhez az adatbázismotor olyan eszközöket biztosít, mint a dinamikus felügyeleti nézetek (DMV-k) és a teljesítményszámlálók.
DMV-k
A következő DMV-k a tempdb
aktuális rendszerállapotáról és a verziótárról, valamint a sorverziósítást használó tranzakciókról nyújtanak információkat.
sys.dm_db_file_space_usage
. Az adatbázis minden fájljának helyhasználati adatait adja vissza. További információt a következő helyen talál: sys.dm_db_file_space_usage (Transact-SQL).sys.dm_db_session_space_usage
. Az oldalfoglalási és felszabadítási tevékenységet adja vissza munkamenetek szerint az adatbázishoz. További információ: sys.dm_db_session_space_usage (Transact-SQL).sys.dm_db_task_space_usage
. Az oldalfoglalási és felszabadítási tevékenységet adja vissza feladatonként az adatbázishoz. További információ: sys.dm_db_task_space_usage (Transact-SQL).sys.dm_tran_top_version_generators
. Egy virtuális táblát ad vissza azoknak az objektumoknak, amelyek a legtöbb verziót állítják elő a verziótárban. Az első 256 összesített rekordhosszt database_id és rowset_id szerint csoportosítja. Ezzel a függvénnyel megtalálhatja a verziótároló legnagyobb felhasználóit. Csak atempdb
verziótárára vonatkozik. További információért lásd: sys.dm_tran_top_version_generators (Transact-SQL).sys.dm_tran_version_store
. Egy virtuális táblát ad vissza, amely az összes verziórekordot megjeleníti a közös verziótárban. Csak atempdb
verziótárára vonatkozik. További információ: sys.dm_tran_version_store (Transact-SQL).sys.dm_tran_version_store_space_usage
. Egy virtuális táblát ad vissza, amely megjeleníti az egyes adatbázisok verziótárrekordjai által használttempdb
teljes területét. Csak atempdb
verziótárára vonatkozik. További információért lásd: sys.dm_tran_version_store_space_usage (Transact-SQL).Jegyzet
A
sys.dm_tran_top_version_generators
és asys.dm_tran_version_store
lekérdezése költséges lehet, mivel mindkettő a teljes verziótárat vizsgálja, ami nagy lehet.sys.dm_tran_version_store_space_usage
hatékony és nem költséges a futtatása, mert nem navigál az egyes verziótár-rekordok között, hanem az összesített verziótárterületet adja vissza, amit aztempdb
elfogyasztott adatbázisonként.sys.dm_tran_active_snapshot_database_transactions
. Egy virtuális táblát ad vissza a sorverziót használó SQL Server-példány összes adatbázisában lévő összes aktív tranzakcióhoz. A rendszertranzakciók nem jelennek meg ebben a DMV-ben. Ha további információra van szüksége, tekintse meg a következőt: sys.dm_tran_active_snapshot_database_transactions (Transact-SQL).sys.dm_tran_transactions_snapshot
. Egy virtuális táblát ad vissza, amely megjeleníti az egyes tranzakciók pillanatképeit. A pillanatkép a sorverziót használó aktív tranzakciók sorszámát tartalmazza. További információ: sys.dm_tran_transactions_snapshot (Transact-SQL).sys.dm_tran_current_transaction
. Egyetlen sort ad vissza, amely a tranzakció sorverziózással kapcsolatos állapotinformációit jeleníti meg az aktuális munkamenetben. További információért lásd: sys.dm_tran_current_transaction (Transact-SQL).sys.dm_tran_current_snapshot
. Egy virtuális táblát ad vissza, amely az összes aktív tranzakciót megjeleníti az aktuális pillanatkép-elkülönítési tranzakció indításakor. Ha az aktuális tranzakció pillanatkép-elkülönítést használ, ez a függvény nem ad vissza sorokat. A DMVsys.dm_tran_current_snapshot
hasonló asys.dm_tran_transactions_snapshot
, azzal a kivételt leszámítva, hogy csak az aktuális pillanatkép aktív tranzakcióit adja vissza. További információért lásd: sys.dm_tran_current_snapshot (Transact-SQL).sys.dm_tran_persistent_version_store_stats
. A gyorsított adatbázis-helyreállítás engedélyezésekor használt adatbázisok állandó verziótárolójának statisztikáit adja vissza. További információért lásd: sys.dm_tran_persistent_version_store_stats (Transact-SQL).
Teljesítményszámlálók
Az alábbi teljesítményszámlálók a tempdb
verziótárat, valamint a sorszinten verziózott tranzakciókat figyelik. A teljesítményszámlálókat a SQLServer:Transactions
teljesítményobjektum tartalmazza.
Szabad terület a tempdb (KB). A
tempdb
adatbázis szabad területének mennyiségét figyeli kilobájtban (KB). A pillanatkép-elkülönítést támogató verziótár kezeléséheztempdb
-ban elegendő szabad helynek kell lennie.Az alábbi képlet a verziótároló méretének hozzávetőleges becslését tartalmazza. Hosszú ideig futó tranzakciók esetén hasznos lehet figyelni a létrehozási és törlési arányt a verziótároló maximális méretének becsléséhez.
[a közös verziótár mérete] = 2 * [a percenként generált verziótár adatai] * [a tranzakció leghosszabb futási ideje (perce)]
A tranzakciók leghosszabb futási ideje nem tartalmazhat online index buildeket. Mivel ezek a műveletek nagyon nagy táblákon hosszú időt is igénybe vehetnek, az online index-buildek külön verziótárat használnak. Az online index buildverzió-tárolójának hozzávetőleges mérete megegyezik a táblázatban módosított adatok mennyiségével, beleértve az összes indexet is, miközben az online index összeállítása aktív.
Verziótárhely mérete (KB). A
tempdb
összes verziótárolójának KB-beli méretét figyeli. Ez az információ segít meghatározni a verziótárolótempdb
adatbázisában szükséges helyet. Az adott számláló folyamatos figyelése egy adott időszakon keresztül hasznos becslést nyújt arról, mekkora további hely szükséges atempdb
-nak.verziógenerálási sebesség (KB/s). A verziólétrehozási arányt másodpercenkénti KB-ban figyeli az
tempdb
összes verziótárolójában.verziótisztítási sebesség (KB/s). A
tempdb
összes verziótárolójában másodpercenkénti KB-ban figyeli a verziókarbantartási arányt.Jegyzet
A verziólétrehozási sebesség (KB/s) és a verziókarbantartási sebesség (KB/s) adatai felhasználhatók
tempdb
helykövetelmények előrejelzésére.Verziótároló egységszáma. A verziótáregységek számát figyeli.
Verziótár egység létrehozása. A sorverziók tárolására létrehozott verziótáregységek teljes számát figyeli a példány elindítása óta.
Verziótár egység csonkolás. A példány elindítása óta csonkolt verziótáregységek teljes számát figyeli. A verziótáregység csonkolt, ha az SQL Server megállapítja, hogy a verziótáregységben tárolt verziósorok egyike sem szükséges az aktív tranzakciók futtatásához.
Frissítés ütközési aránya. Figyeli a frissítési ütközésekkel rendelkező frissítési pillanatkép-tranzakciók és a frissítési pillanatkép-tranzakciók teljes számának arányát.
leghosszabb tranzakció futási ideje. A sorverziók használatával működő tranzakciók közül a leghosszabb futási időt figyeli másodpercekben. Ezzel megállapíthatja, hogy egy tranzakció váratlan ideig fut-e.
Tranzakciók. Az aktív tranzakciók teljes számát figyeli. Ez nem tartalmazza a rendszertranzakciókat.
pillanatkép-tranzakciók. Az aktív pillanatkép-tranzakciók teljes számát figyeli.
Tranzakciók pillanatképének frissítése. Figyeli a frissítési műveleteket végrehajtó aktív pillanatkép-tranzakciók teljes számát.
Nem snapshot verzió nélküli tranzakciók. A verziórekordokat létrehozó aktív nem pillanatkép-tranzakciók teljes számát figyeli.
Jegyzet
A frissítési pillanatkép-tranzakciók és a nemnapshot verziótranzakciók összege a verziógenerálásban részt vevő tranzakciók teljes számát jelöli. A pillanatkép-tranzakciók és a pillanatkép-frissítési tranzakciók különbsége az írásvédett pillanatkép-tranzakciók számát jelöli.
Példa sorverzió-alapú elkülönítési szintre
Az alábbi példák a SNAPSHOT
elkülönítési tranzakciók és a sorverziósítást használó READ COMMITTED
tranzakciók közötti viselkedésbeli különbségeket mutatják be.
Egy. A SNAPSHOT elkülönítésének működése
Ebben a példában egy SNAPSHOT
elkülönítés alatt futó tranzakció beolvassa azokat az adatokat, amelyeket aztán egy másik tranzakció módosít. A SNAPSHOT
tranzakció nem blokkolja a másik tranzakció által végrehajtott frissítési műveletet, és továbbra is beolvassa az adatokat a verziószámozott sorból, figyelmen kívül hagyva az adatmódosítást. Amikor azonban a SNAPSHOT
tranzakció megpróbálja módosítani a másik tranzakció által már módosított adatokat, a SNAPSHOT
tranzakció hibát okoz, és leáll.
Az 1. munkamenet során:
USE AdventureWorks2022;
GO
-- Enable snapshot isolation on the database.
ALTER DATABASE AdventureWorks2022 SET ALLOW_SNAPSHOT_ISOLATION ON;
GO
-- Start a snapshot transaction
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
GO
BEGIN TRANSACTION;
-- This SELECT statement will return
-- 48 vacation hours for the employee.
SELECT BusinessEntityID, VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
A 2. munkamenet során:
USE AdventureWorks2022;
GO
-- Start a transaction.
BEGIN TRANSACTION;
-- Subtract a vacation day from employee 4.
-- Update is not blocked by session 1 since
-- under snapshot isolation shared locks are
-- not requested.
UPDATE HumanResources.Employee
SET VacationHours = VacationHours - 8
WHERE BusinessEntityID = 4;
-- Verify that the employee now has 40 vacation hours.
SELECT VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
Az 1. munkamenet során:
-- Reissue the SELECT statement - this shows
-- the employee having 48 vacation hours. The
-- snapshot transaction is still reading data from
-- the older, versioned row.
SELECT BusinessEntityID, VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
A 2. munkamenet során:
-- Commit the transaction; this commits the data
-- modification.
COMMIT TRANSACTION;
GO
Az 1. munkamenet során:
-- Reissue the SELECT statement - this still
-- shows the employee having 48 vacation hours
-- even after the other transaction has committed
-- the data modification.
SELECT BusinessEntityID, VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
-- Because the data has been modified outside of the
-- snapshot transaction, any further data changes to
-- that data by the snapshot transaction will cause
-- the snapshot transaction to fail. This statement
-- will generate a 3960 error and the transaction will
-- terminate.
UPDATE HumanResources.Employee
SET SickLeaveHours = SickLeaveHours - 8
WHERE BusinessEntityID = 4;
-- Undo the changes to the database from session 1.
-- This will not undo the change from session 2.
ROLLBACK TRANSACTION;
GO
B. A READ COMMITTED elkülönítés használata sorverziók használatával
Ebben a példában egy sorverziót használó READ COMMITTED
tranzakció párhuzamosan fut egy másik tranzakcióval. A READ COMMITTED
tranzakció másképp viselkedik, mint egy SNAPSHOT
tranzakció. A SNAPSHOT
tranzakcióhoz hasonlóan a READ COMMITTED
tranzakció is felolvassa a verziószámozott sorokat, még akkor is, ha a másik tranzakció módosította az adatokat. A SNAPSHOT
tranzakciótól eltérően azonban a READ COMMITTED
tranzakció:
- Beolvassa a módosított adatokat, miután a másik tranzakció véglegesíti az adatmódosításokat.
- Képes frissíteni a másik tranzakció által módosított adatokat, ahol a
SNAPSHOT
tranzakció nem sikerült.
Az 1. munkamenet során:
USE AdventureWorks2022;
GO
-- Enable READ_COMMITTED_SNAPSHOT on the database.
-- For this statement to succeed, this session
-- must be the only connection to the AdventureWorks2022
-- database.
ALTER DATABASE AdventureWorks2022 SET READ_COMMITTED_SNAPSHOT ON;
GO
-- Start a read-committed transaction
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
BEGIN TRANSACTION;
-- This SELECT statement will return
-- 48 vacation hours for the employee.
SELECT BusinessEntityID, VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
A 2. munkamenet során:
USE AdventureWorks2022;
GO
-- Start a transaction.
BEGIN TRANSACTION;
-- Subtract a vacation day from employee 4.
-- Update is not blocked by session 1 since
-- under read-committed using row versioning shared locks are
-- not requested.
UPDATE HumanResources.Employee
SET VacationHours = VacationHours - 8
WHERE BusinessEntityID = 4;
-- Verify that the employee now has 40 vacation hours.
SELECT VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
Az 1. munkamenet során:
-- Reissue the SELECT statement - this still shows
-- the employee having 48 vacation hours. The
-- read-committed transaction is still reading data
-- from the versioned row and the other transaction
-- has not committed the data changes yet.
SELECT BusinessEntityID, VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
A 2. munkamenet során:
-- Commit the transaction.
COMMIT TRANSACTION;
GO
Az 1. munkamenet során:
-- Reissue the SELECT statement which now shows the
-- employee having 40 vacation hours. Being
-- read-committed, this transaction is reading the
-- committed data. This is different from snapshot
-- isolation which reads from the versioned row.
SELECT BusinessEntityID, VacationHours
FROM HumanResources.Employee
WHERE BusinessEntityID = 4;
-- This statement, which caused the snapshot transaction
-- to fail, will succeed with read-committed using row versioning.
UPDATE HumanResources.Employee
SET SickLeaveHours = SickLeaveHours - 8
WHERE BusinessEntityID = 4;
-- Undo the changes to the database from session 1.
-- This will not undo the change from session 2.
ROLLBACK TRANSACTION;
GO
Sorverzió-alapú elkülönítési szintek engedélyezése
Az adatbázis-rendszergazdák az READ_COMMITTED_SNAPSHOT
utasításban szereplő ALLOW_SNAPSHOT_ISOLATION
és ALTER DATABASE
adatbázis-beállítások használatával szabályozhatják a sorverziók adatbázisszintű beállításait.
Ha a READ_COMMITTED_SNAPSHOT
adatbázis beállítása ON
, a beállítás támogatásához használt mechanizmusok azonnal aktiválódnak. A READ_COMMITTED_SNAPSHOT
beállítás beállításakor csak a ALTER DATABASE
parancsot végrehajtó kapcsolat engedélyezett az adatbázisban. Az adatbázisban nem lehet más nyitott kapcsolat, amíg a ALTER DATABASE
nincs befejezve. Az adatbázisnak nem kell egyfelhasználós módban lennie.
A következő Transact-SQL utasítás engedélyezi a READ_COMMITTED_SNAPSHOT
:
ALTER DATABASE AdventureWorks2022 SET READ_COMMITTED_SNAPSHOT ON;
Ha a ALLOW_SNAPSHOT_ISOLATION
adatbázis-beállítás ON
értékre van állítva, az adatbázismotor példánya nem kezdi meg a módosított adatok sorverzióinak generálását, amíg az adatbázisban módosított összes aktív tranzakció be nem fejeződik. Aktív módosítási tranzakciók esetén az adatbázismotor beállítja a PENDING_ON
lehetőség állapotát. Miután az összes módosítási tranzakció befejeződött, a beállítás állapota ON
lesz. A felhasználók nem indíthatnak el SNAPSHOT
tranzakciót az adatbázisban, amíg a beállítás ON
. Hasonlóképpen, az adatbázis egy PENDING_OFF
állapoton halad át, amikor az adatbázis rendszergazdája a ALLOW_SNAPSHOT_ISOLATION
beállítást OFF
.
A következő Transact-SQL utasítás engedélyezi a ALLOW_SNAPSHOT_ISOLATION
:
ALTER DATABASE AdventureWorks2022 SET ALLOW_SNAPSHOT_ISOLATION ON;
Az alábbi táblázat felsorolja és ismerteti a ALLOW_SNAPSHOT_ISOLATION
beállítás állapotát. A ALTER DATABASE
használata a ALLOW_SNAPSHOT_ISOLATION
beállítással nem blokkolja az adatbázis-adatokhoz jelenleg hozzáférő felhasználókat.
Az aktuális adatbázis SNAPSHOT elkülönítésének állapota |
Leírás |
---|---|
OFF |
A SNAPSHOT elkülönítési tranzakciók támogatása nincs aktiválva. Nem engedélyezettek SNAPSHOT elkülönítési tranzakciók. |
PENDING_ON |
Az elkülönítési tranzakciók SNAPSHOT támogatása átmeneti állapotban van (OFF és ON között). A nyitott tranzakcióknak befejeződniük kell.Nem engedélyezettek SNAPSHOT elkülönítési tranzakciók. |
ON |
A SNAPSHOT elkülönítési tranzakciók támogatása aktiválva van.SNAPSHOT tranzakciók engedélyezettek. |
PENDING_OFF |
Az elkülönítési tranzakciók SNAPSHOT támogatása átmeneti állapotban van (ON és OFF között).SNAPSHOT ezután megkezdett tranzakciók nem férnek hozzá az adatbázishoz. A meglévő SNAPSHOT tranzakciók továbbra is hozzáférhetnek az adatbázishoz. A meglévő írási tranzakciók továbbra is verziószámozást használnak ebben az adatbázisban. Az állapot PENDING_OFF nem válik OFF állapottá, amíg az összes SNAPSHOT tranzakció be nem fejeződik, amelyek akkor kezdődtek, amikor az adatbázis SNAPSHOT izolációs állapota ON volt. |
A sys.databases
katalógusnézet segítségével meghatározhatja mindkét sor verziószámozási adatbázis-beállításának állapotát.
A felhasználói táblák és néhány rendszertábla frissítése a master
és msdb
-ben sorverziókat generál.
A ALLOW_SNAPSHOT_ISOLATION
beállítás automatikusan ON
van beállítva a master
és msdb
adatbázisokban, és nem tiltható le.
A felhasználók nem állíthatják be a READ_COMMITTED_SNAPSHOT
opciót ON
-re a master
, tempdb
vagy msdb
esetében.
Verzió-alapú sor elkülönítési szintek használata
A sorverziós keretrendszer mindig engedélyezve van, és több funkció is használja. A sorverzióalapú elkülönítési szintek biztosítása mellett az eseményindítókban és több aktív eredménykészletben (MARS) végzett módosítások támogatására, valamint az online indexműveletek adatolvasásainak támogatására is használható.
A sorverzió-alapú elkülönítési szintek az adatbázis szintjén engedélyezve vannak. Az engedélyezett adatbázisokból objektumokat elérő alkalmazások a következő elkülönítési szintek használatával futtathatnak lekérdezéseket:
READ COMMITTED
, amely sorverziót használ aREAD_COMMITTED_SNAPSHOT
adatbázis beállításávalON
az alábbi kódpélda szerint:ALTER DATABASE AdventureWorks2022 SET READ_COMMITTED_SNAPSHOT ON;
Ha az adatbázis az
READ_COMMITTED_SNAPSHOT
funkcióval működik, azREAD COMMITTED
elkülönítési szinten futó összes lekérdezés sorverziót használ, ami azt jelenti, hogy az olvasási műveletek nem akadályozzák a frissítési műveleteket.A
SNAPSHOT
elkülönítést aALLOW_SNAPSHOT_ISOLATION
adatbázis beállításátON
-re állítva érhetjük el, az alábbi kódrészlet példájában látható módon.ALTER DATABASE AdventureWorks2022 SET ALLOW_SNAPSHOT_ISOLATION ON;
Adatbázisközi lekérdezések használatakor a
SNAPSHOT
elkülönítés alatt futó tranzakciók hozzáférhetnek az adatbázis(ok) azon tábláihoz, amelyekALLOW_SNAPSHOT_ISOLATION
adatbázis-beállítás értékeON
. Ha olyan adatbázisok tábláihoz szeretne hozzáférni, amelyeknél azALLOW_SNAPSHOT_ISOLATION
opció nincsON
-re állítva, módosítani kell az elkülönítési szintet. Az alábbi példakód például egySELECT
utasítást mutat be, amely két táblát illeszt össze, miközben egySNAPSHOT
tranzakció alatt fut. Az egyik tábla olyan adatbázishoz tartozik, amelyben nincs engedélyezveSNAPSHOT
elkülönítés. Ha aSELECT
utasításSNAPSHOT
elkülönítés alatt fut, a művelet végrehajtása sikertelen.SET TRANSACTION ISOLATION LEVEL SNAPSHOT; BEGIN TRANSACTION; SELECT t1.col5, t2.col5 FROM Table1 as t1 INNER JOIN SecondDB.dbo.Table2 as t2 ON t1.col1 = t2.col2;
Az alábbi példakód az eredeti
SELECT
utasítást mutatja be, amelyet úgy módosítottak, hogy egy adott tábla elérésekor a tranzakció elkülönítési szintjeREAD COMMITTED
-re változzon. A módosítás miatt aSELECT
utasítás sikeresen végrehajtódik.SET TRANSACTION ISOLATION LEVEL SNAPSHOT; BEGIN TRANSACTION; SELECT t1.col5, t2.col5 FROM Table1 as t1 WITH (READCOMMITTED) INNER JOIN SecondDB.dbo.Table2 as t2 ON t1.col1 = t2.col2;
A sorverzióalapú elkülönítési szinteket használó tranzakciók korlátozásai
A sorverzióalapú elkülönítési szintek használatakor vegye figyelembe a következő korlátozásokat:
READ_COMMITTED_SNAPSHOT
nem engedélyezhetőtempdb
,msdb
vagymaster
.A globális ideiglenes táblák a
tempdb
-ban vannak tárolva. Ha egySNAPSHOT
tranzakción belüli globális ideiglenes táblákhoz fér hozzá, az alábbiak egyikének kell történnie:- Állítsa be az
ALLOW_SNAPSHOT_ISOLATION
adatbázis opciótON
a(z)tempdb
-ben. - Az utasítás elkülönítési szintjének módosításához használjon elkülönítési tippet.
- Állítsa be az
SNAPSHOT
tranzakciók meghiúsulnak, ha:- Az adatbázis írásvédett lesz a
SNAPSHOT
tranzakció elindítása után, de mielőtt aSNAPSHOT
tranzakció hozzáfér az adatbázishoz. - Ha több adatbázisból fér hozzá objektumokhoz, az adatbázis állapota úgy módosult, hogy az adatbázis-helyreállítás egy
SNAPSHOT
tranzakció elindítása után, de még azelőtt történt, hogy aSNAPSHOT
tranzakció hozzáfér az adatbázishoz. Például: az adatbázisOFFLINE
, majdONLINE
értékre lett állítva, az adatbázis automatikusan bezárult, és újra meg lett nyitva aAUTO_CLOSE
beállításON
beállítása miatt, vagy az adatbázis leválasztva és újracsatlakoztatva lett.
- Az adatbázis írásvédett lesz a
Az elosztott tranzakciók, beleértve az elosztott particionált adatbázisok lekérdezéseit, nem támogatottak
SNAPSHOT
elkülönítése esetén.Az adatbázismotor nem tartja meg a rendszer metaadatainak több verzióját. A táblák és más adatbázis-objektumok (indexek, nézetek, adattípusok, tárolt eljárások és gyakori nyelvi futtatókörnyezeti függvények) adatdefiníciós nyelvi (DDL) utasításai módosítják a metaadatokat. Ha egy DDL-utasítás módosít egy objektumot, az objektumra való egyidejű hivatkozás
SNAPSHOT
elkülönítés esetén aSNAPSHOT
tranzakció meghiúsul.READ COMMITTED
tranzakciókra nem vonatkozik ez a korlátozás, ha aREAD_COMMITTED_SNAPSHOT
adatbázis beállításaON
.Egy adatbázis-rendszergazda például a következő
ALTER INDEX
utasítást hajtja végre.USE AdventureWorks2022; GO ALTER INDEX AK_Employee_LoginID ON HumanResources.Employee REBUILD; GO
A
ALTER INDEX
utasítás végrehajtásakor aktív pillanatkép-tranzakciók hibaüzenetet kapnak, ha aHumanResources.Employee
utasítás végrehajtása után megpróbál hivatkozni aALTER INDEX
táblára. AREAD COMMITTED
sorverziót használó tranzakciókra nincs hatással.Jegyzet
BULK INSERT
műveletek a céltábla metaadatainak módosítását okozhatják (például a kényszerellenőrzések letiltása esetén). Ha ez történik, a tömegesen beszúrt táblákhoz hozzáférő egyidejűSNAPSHOT
elkülönítési tranzakciók meghiúsulnak.
Zárolás és sorverziók testreszabása
A zárolási időkorlát testreszabása
Ha az adatbázismotor egy példánya nem tud zárolni egy tranzakciót, mert egy másik tranzakció már rendelkezik ütköző zárolással az erőforráson, az első tranzakció le lesz tiltva a meglévő zárolás feloldására várva. Alapértelmezés szerint nincs időtúllépési időszak a zárolási várakozásokra, ezért egy tranzakció határozatlan ideig blokkolható lehet.
Jegyzet
A sys.dm_os_waiting_tasks
dinamikus felügyeleti nézettel meghatározhatja, hogy egy tevékenység le van-e tiltva, és mi blokkolja azt. További információkért és példákért lásd: Az SQL Server blokkolási problémáinakismertetése és megoldása.
A LOCK_TIMEOUT
beállítás lehetővé teszi az alkalmazások számára, hogy beállítsanak egy maximális időt, amikor egy utasítás várakozik egy blokkolt erőforráson. Ha egy utasítás a LOCK_TIMEOUT
beállításnál hosszabb ideig várt, a blokkolt utasítás automatikusan törlődik, és az 1222 (Lock request time-out period exceeded
) hibaüzenet jelenik meg. Az utasítást tartalmazó tranzakciók azonban nem lesznek visszaállítva. Ezért az alkalmazásnak rendelkeznie kell egy hibakezelőval, amely képes az 1222-ben megjelenő hibaüzenetet csapdába csalni. Ha egy alkalmazás nem kezeli a hibát, az alkalmazás tovább folytathatja anélkül, hogy tudná, hogy egy tranzakcióban lévő egyes utasítás meg lett szakítva, de a tranzakció aktív marad. Hibák léphetnek fel, mert a tranzakció későbbi utasításai a soha nem végrehajtott utasítástól függhetnek.
Az 1222-es hibaüzenetet lekezelő hibakezelő implementálása lehetővé teszi az alkalmazás számára, hogy kezelje az időtúllépési helyzetet, és javító intézkedést tegyen, például: automatikusan újraküldi a letiltott utasítást, vagy visszaállítja a teljes tranzakciót.
Fontos
Azok az alkalmazások, amelyek explicit tranzakciókat használnak, és megkövetelik a tranzakció leállítását az 1222-as hiba fogadásakor, a hibakezelés részeként explicit módon vissza kell állítaniuk a tranzakciót. E nélkül más utasítások is véletlenül végrehajthatók ugyanazon a munkameneten, miközben a tranzakció aktív marad, ami kötetlen tranzakciónapló-növekedéshez és adatvesztéshez vezethet, ha a tranzakciót később visszaállítják.
Az aktuális LOCK_TIMEOUT
beállítás meghatározásához hajtsa végre a @@LOCK_TIMEOUT
függvényt:
SELECT @@LOCK_TIMEOUT;
GO
Tranzakcióelkülönítési szint testreszabása
READ COMMITTED
az adatbázismotor alapértelmezett elkülönítési szintje. Ha egy alkalmazásnak más elkülönítési szinten kell működnie, a következő módszerekkel állíthatja be az elkülönítési szintet:
- Futtassa a SET TRANSACTION ISOLATION LEVEL utasítást.
- ADO.NET
System.Data.SqlClient
névteret használó alkalmazások aIsolationLevel
metódussal adhatnak meg egySqlConnection.BeginTransaction
beállítást. - Az ADO-t használó alkalmazások beállíthatják a
Autocommit Isolation Levels
tulajdonságot. - Tranzakció indításakor az OLE DB-t használó alkalmazások meghívhatják a
ITransactionLocal::StartTransaction
-t, ahol aisoLevel
a kívánt tranzakció-elkülönítési szintre van beállítva. Az elkülönítési szint autocommit módban történő megadásakor az OLE DB-t használó alkalmazások a kívánt tranzakcióelkülönítési szintre állíthatják aDBPROPSET_SESSION
tulajdonságotDBPROP_SESS_AUTOCOMMITISOLEVELS
. - Az ODBC-t használó alkalmazások a
SQL_COPT_SS_TXN_ISOLATION
használatával állíthatják be aSQLSetConnectAttr
attribútumot.
Az elkülönítési szint megadásakor a munkamenet összes lekérdezésének és adatmanipulációs nyelvének (DML) zárolási viselkedése ezen az elkülönítési szinten működik. Az elkülönítési szint addig marad érvényben, amíg a munkamenet le nem fejeződik, vagy amíg az elkülönítési szint másik szintre nem kerül.
Az alábbi példa a SERIALIZABLE
elkülönítési szintjét állítja be:
USE AdventureWorks2022;
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
GO
BEGIN TRANSACTION;
SELECT BusinessEntityID
FROM HumanResources.Employee;
COMMIT;
GO
Az elkülönítési szint felülbírálható az egyes lekérdezések vagy DML-utasítások esetében, ha szükséges, egy táblaszintű utasítás megadásával. A táblaszintű utasítás megadása nem befolyásolja a munkamenet többi utasítását.
Az aktuálisan beállított tranzakcióelkülönítési szint meghatározásához használja a DBCC USEROPTIONS
utasítást az alábbi példában látható módon. Az eredményhalmaz eltérhet a rendszer eredményhalmazától.
USE AdventureWorks2022;
GO
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
GO
DBCC USEROPTIONS;
GO
Itt van az eredményhalmaz.
Set Option Value
---------------------------- -------------------------------------------
textsize 2147483647
language us_english
dateformat mdy
datefirst 7
... ...
Isolation level repeatable read
(14 row(s) affected)
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Zárolási tippek
Az egyes táblahivatkozásokhoz megadhatók zárolási utasítások a SELECT
, INSERT
, UPDATE
, DELETE
és MERGE
utasításokban. A tippek meghatározzák, hogy milyen típusú zárolást vagy sorverziót használ az adatbázismotor példánya a táblaadatokhoz. Táblázatszintű zárolási tippek akkor használhatók, ha az objektumon beszerzett zárolástípusok finomabb szabályozására van szükség. Ezek a zárolási tippek felülírják a munkamenet aktuális tranzakcióelkülönítési szintjét.
Jegyzet
Ha engedélyezve van az optimalizált zárolás, a zárolási tippek nem ajánlottak. Bár a tábla- és lekérdezési javaslatokat figyelembe veszik, csökkentik az optimalizált zárolás előnyeit. További információért lásd Az optimalizált zárolás mellőzése zárolási tippekkel.
Az egyes zárolási tippekről és azok viselkedéséről további információt Table Hints (Transact-SQL)című témakörben talál.
Jegyzet
Javasoljuk, hogy táblázatszintű zárolási tippeket használjon az alapértelmezett zárolási viselkedés módosításához, ha szükséges. A zárolási szint kényszerítése hátrányosan befolyásolhatja az egyidejűséget.
Előfordulhat, hogy az adatbázismotornak zárolásokat kell beszereznie a metaadatok olvasása során, még akkor is, ha egy utasítást zárolási tipptel dolgoz fel, amely megakadályozza a megosztott zárolásokra vonatkozó kéréseket az adatok olvasása során. Például egy SELECT
utasítás, amely az READ UNCOMMITTED
elkülönítési szinten fut, vagy a NOLOCK
tipp használatával nem szerez be megosztási zárolásokat az adatok olvasásakor, de előfordulhat, hogy rendszerkatalógus-nézet olvasásakor bizonyos esetekben zárolást kér. Ez azt jelenti, hogy egy ilyen SELECT
utasítás blokkolható, ha egy egyidejű tranzakció módosítja a tábla metaadatait.
Az alábbi példában látható módon, ha a tranzakcióelkülönítési szint SERIALIZABLE
van beállítva, és a táblaszintű zárolási tippet NOLOCK
a SELECT
utasítással használja, a rendszer nem szerzi be a SERIALIZABLE
tranzakciók fenntartásához általában használt kulcstartomány-zárolásokat.
USE AdventureWorks2022;
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
GO
BEGIN TRANSACTION;
GO
SELECT JobTitle
FROM HumanResources.Employee WITH (NOLOCK);
GO
-- Get information about the locks held by
-- the transaction.
SELECT resource_type,
resource_subtype,
request_mode
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID;
-- End the transaction.
ROLLBACK;
GO
Az egyetlen zárolás, amely a HumanResources.Employee
-ra hivatkozik, egy sémastabilitási (Sch-S
) zárolás. Ebben az esetben a szerializálhatóság már nem garantált.
A LOCK_ESCALATION
ALTER TABLE
lehetősége megakadályozza a táblazárolást a zárolás eszkalálása során, és engedélyezi a HoBT (partíció) zárolását particionált táblákon. Ez a beállítás nem zárolási tipp, és zárolás eszkalálásánakcsökkentésére használható. További információért lásd: ALTER TABLE (Transact-SQL).
Index zárolásának testreszabása
Az adatbázismotor dinamikus zárolási stratégiát használ, amely automatikusan kiválasztja a lekérdezések legjobb részletességét a legtöbb esetben. Azt javasoljuk, hogy ne bírálja felül az alapértelmezett zárolási szinteket, kivéve, ha a tábla- vagy indexhozzáférési minták jól érthetőek és konzisztensek, és az erőforrás-versengési problémát meg kell oldani. A zárolási szint felülbírálása jelentősen akadályozhatja a táblákhoz vagy indexekhez való egyidejű hozzáférést. Ha például csak a táblaszintű zárolásokat adja meg egy olyan nagy táblán, amelyhez a felhasználók nagy mértékben hozzáférnek, szűk keresztmetszeteket okozhat, mivel a felhasználóknak várniuk kell a táblaszintű zárolás feloldására a táblázathoz való hozzáférés előtt.
Vannak olyan esetek, amikor előnyös lehet az oldal- vagy sorzárolás letiltása, ha a hozzáférési minták jól érthetőek és konzisztensek. Az adatbázis-alkalmazások például egy olyan keresési táblát használnak, amely hetente frissül egy kötegfolyamatban. Az egyidejű olvasók megosztott (S
) zárolással férnek hozzá a táblához, és a heti kötegelt frissítés kizárólagos (X
) zárolással éri el a táblát. Ha kikapcsolja az oldal- és sorzárolást a táblán, azzal a hét során csökkenti a zárolási többletterhelést azáltal, hogy lehetővé teszi az olvasók számára, hogy egyidejűleg hozzáférjenek a táblázathoz megosztott táblazárakon keresztül. A kötegelt feladat futtatásakor hatékonyan végezheti el a frissítést, mert kizárólagos táblazárolást kap.
Előfordulhat, hogy az oldal- és sorzárolás kikapcsolása nem elfogadható, mert a heti kötegfrissítés megakadályozza, hogy az egyidejű olvasók hozzáférjenek a táblához a frissítés futtatásakor. Ha a kötegelt feladat csak néhány sort vagy lapot módosít, módosíthatja a zárolási szintet úgy, hogy lehetővé tegye a sor- vagy oldalszintű zárolást, ami lehetővé teszi, hogy más munkamenetek blokkolás nélkül olvassanak a táblázatból. Ha a kötegelt feladat nagyszámú frissítést tartalmaz, a táblára vonatkozó kizárólagos zárolás megszerzése lehet a legjobb módja annak, hogy a kötegelt feladat hatékonyan fusson.
Egyes számítási feladatokban holtpont típusa akkor fordulhat elő, ha két egyidejű művelet sorzárolásokat szerez be ugyanazon a táblán, majd letiltja egymást, mert mindkettőnek zárolnia kell az oldalt. A sorzár letiltása az egyik műveletet várakozásra készteti, így elkerülve a holtpontot. További információ a holtpontokról: Holtpontok útmutató.
Az indexen használt zárolás részletessége a CREATE INDEX
és ALTER INDEX
utasítások használatával állítható be. Emellett a CREATE TABLE
és a ALTER TABLE
utasítások segítségével is beállíthatja a zárolás részletességét PRIMARY KEY
és UNIQUE
korlátozásokon. A visszamenőleges kompatibilitás érdekében a sp_indexoption
rendszer által tárolt eljárás is beállíthatja a részletességet. Az adott index aktuális zárolási beállításának megjelenítéséhez használja a INDEXPROPERTY
függvényt. Az oldalszintű zárolások, a sorszintű zárolások, illetve az oldalszintű és a sorszintű zárolások is letilthatók egy adott index esetében.
Letiltott zárolások | Az indexet a következő érheti el: |
---|---|
Oldalszint | Sorszintű és táblázatszintű zárolások |
Sorszint | Oldalszintű és táblázatszintű zárolások |
Oldalszint és sorszint | Táblaszintű zárolások |
Speciális tranzakcióinformációk
Egymásba ágyazott tranzakciók
Az explicit tranzakciók beágyazhatók. Ez elsősorban olyan tárolt eljárások tranzakcióinak támogatására szolgál, amelyek egy tranzakcióban már szereplő folyamatból vagy aktív tranzakcióval nem rendelkező folyamatokból hívhatók meg.
Az alábbi példa a beágyazott tranzakciók használatát mutatja be. Ha a TransProc
-at egy aktív tranzakció esetén hívjuk meg, a beágyazott tranzakció kimenetét a külső tranzakció a TransProc
-en keresztül szabályozza, és a INSERT
utasítások a külső tranzakció véglegesítése vagy visszaállítása alapján lesznek véglegesítve vagy visszaállítva. Ha TransProc
olyan folyamat hajtja végre, amely nem rendelkezik függőben lévő tranzakcióval, az eljárás végén a COMMIT TRANSACTION
véglegesíti a INSERT
utasításokat.
SET QUOTED_IDENTIFIER OFF;
GO
SET NOCOUNT OFF;
GO
CREATE TABLE TestTrans
(
ColA INT PRIMARY KEY,
ColB CHAR(3) NOT NULL
);
GO
CREATE PROCEDURE TransProc
@PriKey INT,
@CharCol CHAR(3)
AS
BEGIN TRANSACTION InProc;
INSERT INTO TestTrans VALUES (@PriKey, @CharCol);
INSERT INTO TestTrans VALUES (@PriKey + 1, @CharCol);
COMMIT TRANSACTION InProc;
GO
/* Start a transaction and execute TransProc. */
BEGIN TRANSACTION OutOfProc;
GO
EXEC TransProc 1, 'aaa';
GO
/* Roll back the outer transaction, this will
roll back TransProc's nested transaction. */
ROLLBACK TRANSACTION OutOfProc;
GO
EXECUTE TransProc 3,'bbb';
GO
/*
The following SELECT statement shows only rows 3 and 4 are
still in the table. This indicates that the commit
of the inner transaction from the first EXECUTE statement of
TransProc was overridden by the subsequent roll back of the
outer transaction.
*/
SELECT *
FROM TestTrans;
GO
A belső tranzakciók véglegesítését az adatbázismotor figyelmen kívül hagyja, ha egy külső tranzakció aktív. A tranzakció vagy véglegesítésre kerül, vagy visszagördül, attól függően, hogy a legkülső tranzakció végén véglegesítés vagy visszagördülés történik. Ha a külső tranzakció véglegesítve van, a belső beágyazott tranzakciók is véglegesítve lesznek. Ha a külső tranzakció vissza lett gördülve, akkor az összes belső tranzakció is vissza lesz állítva, függetlenül attól, hogy a belső tranzakciók egyedileg lettek-e véglegesítva.
Minden COMMIT TRANSACTION
vagy COMMIT WORK
hívás az utoljára végrehajtott BEGIN TRANSACTION
-re vonatkozik. Ha a BEGIN TRANSACTION
utasítások beágyazottak, akkor egy COMMIT
utasítás csak az utolsó beágyazott tranzakcióra vonatkozik, amely a legbelső tranzakció. Még akkor is, ha egy beágyazott tranzakción belüli COMMIT TRANSACTION transaction_name
utasítás a külső tranzakció tranzakciónevére hivatkozik, a véglegesítés csak a legbelső tranzakcióra vonatkozik.
Egy transaction_name
utasítás ROLLBACK TRANSACTION
paramétere nem hivatkozhat a belső tranzakcióra nevesített beágyazott tranzakciók halmazában.
transaction_name
csak a legkülső tranzakció tranzakciójának nevére hivatkozhat. Ha a külső tranzakció nevét használó ROLLBACK TRANSACTION transaction_name
utasítás végrehajtása a beágyazott tranzakciók bármelyik szintjén történik, az összes beágyazott tranzakció vissza lesz állítva. Ha egy ROLLBACK WORK
paraméter nélküli ROLLBACK TRANSACTION
vagy transaction_name
utasítás végrehajtása a beágyazott tranzakciók bármely szintjén történik, az összes beágyazott tranzakciót visszaállítja, beleértve a legkülső tranzakciót is.
A @@TRANCOUNT
függvény rögzíti az aktuális tranzakció beágyazási szintjét. Minden BEGIN TRANSACTION
utasítás egyet hozzáad @@TRANCOUNT
-hez. Minden COMMIT TRANSACTION
vagy COMMIT WORK
utasítás eggyel csökkenti @@TRANCOUNT
-t. Egy ROLLBACK WORK
vagy egy ROLLBACK TRANSACTION
utasítás, amely nem rendelkezik tranzakciónévvel, visszavonja az összes beágyazott tranzakciót, és a @@TRANCOUNT
értékét 0-ra csökkenti. A beágyazott tranzakciók halmazában a legkülső tranzakció nevét használó ROLLBACK TRANSACTION
visszavonja az összes beágyazott tranzakciót, és csökkenti a @@TRANCOUNT
értékét 0-ra. Annak megállapításához, hogy már szerepel-e egy tranzakcióban, SELECT @@TRANCOUNT
annak megállapításához, hogy az 1 vagy több-e. Ha @@TRANCOUNT
egyenlő 0-val, akkor nem vagy tranzakcióban.
Kötött munkamenetek használata
A kötött munkamenetek megkönnyítik a műveletek összehangolását több munkamenetben ugyanazon a kiszolgálón. A kötött munkamenetek lehetővé teszik, hogy két vagy több munkamenet ugyanazt a tranzakciót és zárolást ossza meg, és zárolási ütközések nélkül dolgozhat ugyanazon az adatokon. A kötött munkamenetek több munkamenetből is létrehozható ugyanabban az alkalmazásban, vagy több különálló munkamenetet tartalmazó alkalmazásból.
Ha részt szeretne venni egy kötött munkamenetben, egy munkamenet meghívja sp_getbindtoken vagy srv_getbindtoken (Open Data Servicesen keresztül) egy kötési jogkivonat lekéréséhez. A kötési jogkivonat egy karaktersztring, amely egyedileg azonosítja az egyes kötött tranzakciókat. A kötési jogkivonatot ezután a rendszer elküldi a többi munkamenetnek, hogy az aktuális munkamenethez legyen kötve. A többi munkamenet az első munkamenetből kapott kötési jogkivonat használatával sp_bindsession
meghívásával köti a tranzakcióhoz.
Jegyzet
A munkamenetnek aktív felhasználói tranzakcióval kell rendelkeznie ahhoz, hogy sp_getbindtoken
vagy srv_getbindtoken
sikeres legyen.
A tokeneket továbbítani kell az alkalmazáskódból, amely létrehozza az első munkamenetet, azokhoz az alkalmazáskódokhoz, amelyek ezt követően a munkameneteiket az első munkamenethez kapcsolják. Nincs Transact-SQL utasítás vagy API-függvény, amellyel egy alkalmazás lekérheti egy másik folyamat által indított tranzakció kötési jogkivonatát. A kötési jogkivonatok továbbítására használható módszerek némelyike a következők:
Ha a munkamenetek mindegyike ugyanabból az alkalmazásfolyamatból indul ki, a kötési jogkivonatok tárolhatók a globális memóriában, vagy paraméterként továbbíthatók függvényekbe.
Ha a munkamenetek különálló alkalmazásfolyamatokból készülnek, a kötési jogkivonatok átvitele folyamatközi kommunikációval (IPC) történik, például távoli eljáráshívással (RPC) vagy dinamikus adatcserével (DDE).
A kötési tokenek az adatbázismotor példányában egy táblában tárolhatók, amelyet az első munkamenethez való kötést igénylő folyamatok olvashatnak.
A kötött munkamenetek halmazában egyszerre csak egy munkamenet lehet aktív. Ha egy munkamenet utasítást hajt végre a példányon, vagy a példánytól függőben van az eredmény, az ugyanahhoz a jogkivonathoz kötött másik munkamenet sem férhet hozzá a példányhoz, amíg az aktuális munkamenet nem fejezi be az aktuális utasítás feldolgozását vagy megszakítását. Ha a példány egy másik kötött munkamenetből származó utasítás feldolgozásával van elfoglalva, hibaüzenet jelenik meg, amely azt jelzi, hogy a tranzakcióterület használatban van, és a munkamenetnek később újra meg kell próbálkoznia.
A munkamenetek kötésekor minden munkamenet megtartja az elkülönítési szintet. Az SET TRANSACTION ISOLATION LEVEL
használata az egyik munkamenet elkülönítési szintjének módosításához nincs hatással az ugyanazon jogkivonathoz kötött többi munkamenet beállítására.
Kötött munkamenetek típusai
A kötött munkamenetek két típusa helyi és elosztott.
Helyi kötött munkamenet Lehetővé teszi, hogy a kötött munkamenetek megosztják egy tranzakció tranzakcióterét az adatbázismotor egyetlen példányában.
Elosztott kötött munkamenet Lehetővé teszi, hogy a kötött munkamenetek ugyanazt a tranzakciót két vagy több példányon is megosztják, amíg a teljes tranzakció véglegesítése vagy visszaállítása a Microsoft Distributed Transaction Coordinator (MS DTC) használatával történik.
Az elosztott kötött munkameneteket nem egy karakteres sztringes bind token azonosítja, hanem elosztott tranzakció-azonosító számok. Ha egy kötött munkamenet részt vesz egy helyi tranzakcióban, és egy RPC-t hajt végre egy távoli kiszolgálón SET REMOTE_PROC_TRANSACTIONS ON
, a helyi kötött tranzakció automatikusan előléptet egy elosztott kötött tranzakcióra az MS DTC által, és elindul egy MS DTC-munkamenet.
Mikor érdemes kötött munkameneteket használni?
Az SQL Server korábbi verzióiban a kötött munkameneteket elsősorban kiterjesztett tárolt eljárások fejlesztésére használták, amelyeknek Transact-SQL utasításokat kell végrehajtaniuk az őket meghívó folyamat nevében. Az, hogy a hívási folyamat egy kötési jogkivonatot ad át egy paraméterként a kiterjesztett tárolt eljárásnak, lehetővé teszi az eljárás számára, hogy csatlakozzon a hívási folyamat tranzakciós teréhez, ezáltal integrálva a kiterjesztett tárolt eljárást a hívási folyamattal.
Az adatbázismotorban a CLR használatával írt tárolt eljárások biztonságosabbak, méretezhetők és stabilabbak, mint a kiterjesztett tárolt eljárások. A CLR által tárolt eljárások a SqlContext
objektummal csatlakoznak a hívási munkamenet környezetéhez, nem pedig sp_bindsession
.
A kötött munkamenetek háromszintű alkalmazások fejlesztésére használhatók, amelyekben az üzleti logika különálló programokba van beépítve, amelyek együttműködve működnek egyetlen üzleti tranzakción. Ezeket a programokat kódolni kell, hogy gondosan összehangolják az adatbázishoz való hozzáférésüket. Mivel a két munkamenet ugyanazokkal a zárolásokkal rendelkezik, a két program nem próbálja meg egyszerre módosítani ugyanazokat az adatokat. A tranzakció részeként bármikor csak egy munkamenet végezhet munkát; nem lehet párhuzamos végrehajtás. A tranzakció csak jól meghatározott hozampontokon kapcsolható át a munkamenetek között, például amikor az összes DML-utasítás befejeződött, és az eredmények lekérése megtörtént.
Hatékony tranzakciók kódolása
Fontos, hogy a tranzakciók a lehető legrövidebbek maradjanak. A tranzakció indításakor az adatbázis-kezelő rendszernek (DBMS) a tranzakció végéig számos erőforrást kell tárolnia a tranzakció atomitásának, konzisztenciájának, elkülönítésének és tartósságának (ACID) védelme érdekében. Ha az adatok módosulnak, a módosított sorokat kizárólagos zárolásokkal kell védeni, amelyek megakadályozzák, hogy bármely más tranzakció beolvassa a sorokat, és a kizárólagos zárolásokat a tranzakció véglegesítése vagy visszaállítása előtt kell tartani. A tranzakcióelkülönítési szint beállításaitól függően SELECT
utasítások olyan zárolásokat szerezhetnek be, amelyeket a tranzakció véglegesítéséig vagy visszaállításáig kell tartani. Különösen a sok felhasználóval rendelkező rendszerek esetében a tranzakciókat a lehető legrövidebb ideig kell tartani, hogy az egyidejű kapcsolatok között csökkenjen az erőforrások zárolási versengése. Előfordulhat, hogy a hosszú ideig futó, nem hatékony tranzakciók nem okoznak problémát kis számú felhasználóval, de nagyon problémásak egy több ezer felhasználót tartalmazó rendszerben. Az SQL Server 2014 -től (12.x) kezdődően az adatbázismotor támogatja a késleltetett tartós tranzakciókat. A késleltetett tartós tranzakciók javíthatják a méretezhetőséget és a teljesítményt, de nem garantálják a tartósságot. További információért lásd: Tranzakció tartósságának ellenőrzése.
A kód irányelvei
A hatékony tranzakciók kódolásának irányelvei:
Ne igényelje a felhasználóktól a tranzakció során kapott adatokat. A tranzakciók megkezdése előtt kérje le a felhasználóktól az összes szükséges adatot. Ha a tranzakció során további felhasználói bemenetre van szükség, akkor a felhasználói bevitel megadása után indítsa újra az aktuális tranzakciót. Még akkor is, ha a felhasználók azonnal válaszolnak, az emberi reakcióidők jelentősen lassabbak, mint a számítógép sebessége. A tranzakció által birtokolt összes erőforrás rendkívül hosszú ideig van tárolva, ami blokkolási problémákat okozhat. Ha a felhasználók nem válaszolnak, a tranzakció aktív marad, és zárolja a kritikus erőforrásokat, amíg nem válaszolnak, ami néhány percig vagy akár órákig sem fordulhat elő.
Ha lehetséges, ne nyisson meg tranzakciót az adatok böngészése közben. A tranzakciókat csak akkor szabad elindítani, ha az összes előzetes adatelemzés befejeződött.
Tartsa a lehető legrövidebb ideig a tranzakciót. Miután megismerte a végrehajtandó módosításokat, kezdjen el egy tranzakciót, hajtsa végre a módosítási utasításokat, majd azonnal véglegesítse vagy visszaállítsa a módosításokat. Ne nyissa meg a tranzakciót, mielőtt szükség lenne rá.
A blokkolás csökkentése érdekében érdemes lehet sorverzióalapú elkülönítési szintet használni az írásvédett lekérdezésekhez.
Használja intelligensen az alacsonyabb tranzakcióelkülönítési szinteket. Számos alkalmazást lehet úgy kódolni, hogy a
READ COMMITTED
tranzakcióelkülönítési szintet használja. Kevés tranzakcióhoz szükséges aSERIALIZABLE
tranzakcióelkülönítési szint.Intelligensen használja az optimista egyidejű végrehajtási lehetőségeket. Olyan rendszerekben, amelyekben alacsony az egyidejű frissítések valószínűsége, az időnkénti "valaki más módosította az adatokat az olvasás után" hibával kapcsolatos többletterhelés sokkal alacsonyabb lehet, mint a sorok olvasás közbeni zárolásának többletterhelése.
A lehető legkevesebb adat elérése tranzakció közben. Ez csökkenti a zárolt sorok számát, ezáltal csökkenti a tranzakciók közötti versengést.
Kerülje a pesszimista zárolási útmutatásokat, például
HOLDLOCK
, amikor csak lehetséges. Az olyan elkülönítési szintek, mint aHOLDLOCK
vagy aSERIALIZABLE
, azt okozhatják, hogy a folyamatok még a megosztott zárolások esetén is várakozzanak, és csökkentik az egyidejűséget.Ha lehetséges, kerülje az implicit tranzakciók használatát. Az implicit tranzakciók természetükből adódóan kiszámíthatatlan viselkedést okozhatnak. Lásd implicit tranzakciók és egyidejűségi problémák.
Implicit tranzakciók és az egyidejűség és az erőforrásproblémák elkerülése
Az egyidejűség és az erőforrásproblémák elkerülése érdekében gondosan kezelje az implicit tranzakciókat. Implicit tranzakciók használatakor a következő Transact-SQL utasítás COMMIT
vagy ROLLBACK
után automatikusan elindít egy új tranzakciót. Ez egy új tranzakció megnyitását okozhatja, miközben az alkalmazás végigböngészi az adatokat, vagy még akkor is, ha a felhasználótól kér bemenetet. Az adatmódosítások védelméhez szükséges utolsó tranzakció befejezése után kapcsolja ki az implicit tranzakciókat, amíg ismét tranzakcióra nincs szükség az adatmódosítások védelméhez. Ez a folyamat lehetővé teszi, hogy az adatbázismotor automatikus üzenetküldési módot használjon, miközben az alkalmazás adatokat böngész, és bemenetet kér a felhasználótól.
Emellett ha engedélyezve van a SNAPSHOT
elkülönítési szint, bár egy új tranzakció nem fog zárolásokat tárolni, egy hosszan futó tranzakció megakadályozza a régi verziók eltávolítását a verziótárból.
Hosszú ideig futó tranzakciók kezelése
A hosszú ideig futó tranzakció olyan aktív tranzakció, amelyet nem véglegesítettek, vagy nem vontak vissza időben. Ha például egy tranzakció elejét és végét a felhasználó vezérli, a hosszú ideig futó tranzakciók tipikus oka, hogy egy felhasználó elindít egy tranzakciót, majd kilép, amíg a tranzakció a felhasználó válaszára vár.
A hosszú ideig futó tranzakciók komoly problémákat okozhatnak az adatbázisok esetében az alábbiak szerint:
Ha egy kiszolgálópéldány leáll, miután egy aktív tranzakció számos nem véglegesített módosítást hajtott végre, a későbbi újraindítás helyreállítási fázisa sokkal tovább tarthat, mint a
recovery interval
kiszolgálókonfigurációs beállítás vagy aALTER DATABASE ... SET TARGET_RECOVERY_TIME
beállítás által megadott idő. Ezek a beállítások az aktív és a közvetett ellenőrzőpontokat szabályozzák. Az ellenőrzőpontok típusairól további információt Adatbázis-ellenőrzőpontok (SQL Server)című témakörben talál.Ami még ennél is fontosabb, hogy bár a várakozási tranzakció nagyon kevés naplót generálhat, mégis akadályozza a napló csonkolását, ami miatt a tranzakciónapló növekedhet és akár teljesen megtelhet is. Ha a tranzakciónapló kitöltődik, az adatbázis nem tud több írást végrehajtani. További információ: SQL Server tranzakciónapló-architektúrája és felügyeleti útmutatója, A teljes tranzakciónapló (SQL Server 9002-s hiba)hibaelhárítása és a tranzakciónapló .
Fontos
Az Azure SQL Database-ben a rendszer automatikusan leállítja az inaktív tranzakciókat (a tranzakciónaplóba hat órán át nem írt tranzakciókat) az erőforrások felszabadítása érdekében.
Hosszú ideig futó tranzakciók felderítése
A hosszú ideig futó tranzakciók kereséséhez használja az alábbiak egyikét:
sys.dm_tran_database_transactions
Ez a dinamikus felügyeleti nézet az adatbázis szintjén visszaadja a tranzakciók adatait. Hosszú ideig futó tranzakció esetén a fontos oszlopok közé tartozik az első naplórekord ideje (
database_transaction_begin_time
), a tranzakció aktuális állapota (database_transaction_state
) és a naplósorozat-szám (LSN) a tranzakciónapló kezdő rekordjánál (database_transaction_begin_lsn
).További információ: sys.dm_tran_database_transactions (Transact-SQL).
DBCC OPENTRAN
Ez az utasítás lehetővé teszi a tranzakció tulajdonosának felhasználói azonosítójának azonosítását, így potenciálisan nyomon követheti a tranzakció forrását a megfelelő leállításhoz (véglegesítéshez vagy visszaállításhoz). További információ: DBCC OPENTRAN (Transact-SQL).
Tranzakció megszüntetése
Ha egy tranzakciót egy adott munkameneten szeretne megszakítani, használja a KILL
utasítást. Ezt az utasítást azonban nagyon óvatosan kell használni, különösen kritikus folyamatok futtatásakor. További információ: KILL (Transact-SQL).
Holtpontok
A holtpontok a zárolással kapcsolatos összetett témakör, de eltérnek a blokkolástól.
- További információ a holtpontokról, beleértve a monitorozást, a diagnózist és a mintákat, olvassa el az útmutatót a holtpontokról.
- Az Azure SQL Database-hez tartozó holtpontokról további információt Az Azure SQL Database-holtpontok elemzése és megakadályozása című témakörben talál.