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.
Vonatkozik a következőkre:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Analitikai Platform System (PDW)
SQL adatbázis a Microsoft Fabric-ben
Ez a cikk részletesen ismerteti az adatbázismotor holtpontjait. A holtpontokat az adatbázis konkurens, egyidejű zárolásai okozzák, gyakran többlépéses tranzakciókban. A tranzakciókról és a zárolásokról további információt a tranzakciózárolási és a sorverzió-verziószámozási útmutatóban talál.
Az Azure SQL Database-ben és a Fabricben található SQL Database-ben található holtpontok azonosításáról és megelőzéséről további információt az Azure SQL Database és az SQL Database holtpontjainak elemzése és megakadályozása a Fabricben című témakörben talál.
Holtpontok ismertetése
Holtpont akkor fordul elő, ha két vagy több tevékenység véglegesen blokkolja egymást, ha mindegyik tevékenység zárol egy olyan erőforrást, amelyet a többi tevékenység zárolni próbál. Például:
Az A tranzakció egy megosztott zárolást szerez be az 1. sorban.
A B tranzakció megosztott zárolást szerez meg a 2. soron.
Az A tranzakció most kizárólagos zárolást kér a 2. sorban, és addig lesz letiltva, amíg a B tranzakció be nem fejeződik, és fel nem oldja a megosztott zárolást a 2. sorban.
A B tranzakció mostantól kizárólagos zárolást kér az 1. sorban, és addig lesz letiltva, amíg az A tranzakció be nem fejeződik, és fel nem oldja az 1. sorban található megosztott zárolást.
Az A tranzakció nem fejezhető be, amíg a B tranzakció be nem fejeződik, a B tranzakciót azonban az A tranzakció blokkolja. Ezt a feltételt ciklikus függőségnek is nevezik: Az A tranzakció függ a B tranzakciótól, a B tranzakció pedig az A tranzakciótól való függőség révén zárja be a kört.
Mindkét tranzakció a holtpontban örökké vár, hacsak egy külső folyamat nem töri meg a holtpontot. Az adatbázismotor holtpont-figyelője rendszeresen ellenőrzi a holtponton lévő feladatokat. Ha a figyelő ciklikus függőséget észlel, kiválasztja az egyik feladatot áldozatként, és hibával szakítja meg a tranzakciót. Ez lehetővé teszi, hogy a másik tevékenység végrehajtsa a tranzakciót. A hibával végződő tranzakcióval rendelkező alkalmazás újrapróbálkozza a tranzakciót, amely általában a többi holtpontra irányuló tranzakció befejeződése után fejeződik be.
A holtpontot gyakran összekeverik a szokásos blokkolással. Amikor egy tranzakció egy másik tranzakció által zárolt erőforrás zárolását kéri, a kérelmező tranzakció megvárja a zárolás feloldását. Alapértelmezés szerint az adatbázismotor tranzakciói nem időtúllépést hajtanak végre, kivéve, ha LOCK_TIMEOUT be van állítva. A kérő tranzakció blokkolva van, nincs holtpontban, mert a kérő tranzakció nem tett semmit a zároló tranzakció blokkolásához. Végül a tulajdonos tranzakció befejeződik és felszabadítja a zárolást, majd a kérelmező tranzakció megkapja a zárolást és folytatja. A holtpontok szinte azonnal megoldódnak, míg a blokkolás elméletileg határozatlan ideig is fennállhat. A holtpontokat néha halálos ölelésként is emlegetik.
Holtpont minden olyan rendszeren előfordulhat, amely több szálból áll, nem csak egy relációs adatbázis-kezelő rendszeren, hanem az adatbázis-objektumok zárolásán kívüli erőforrások esetében is. Egy többszálas operációs rendszer szálai például egy vagy több erőforrást, például memóriablokkokat szerezhetnek be. Ha a beolvasandó erőforrás jelenleg egy másik szál tulajdonában van, előfordulhat, hogy az első szálnak meg kell várnia, amíg a tulajdonos szál felszabadítja a célerőforrást. A várakozási szálról azt mondják, hogy függősége van az adott erőforrás tulajdonosi szálához. Az adatbázismotor egy példányában a munkamenetek holtpontot jelenthetnek, ha nem adatbázis-erőforrásokat, például memóriát vagy szálakat szereznek be.
Az ábrán a T1 tranzakció függ a T2 tranzakciótól a Part tábla zárolási erőforrás miatt. Hasonlóképpen, a T2 tranzakció függ a T1 tranzakciótól a Supplier táblazár erőforrás miatt. Mivel ezek a függőségek ciklust alkotnak, holtpont van a T1 és a T2 tranzakciók között.
Íme egy általánosabb ábra a holtpontról:
A T1 tevékenység zárolta az R1 erőforrást (ezt az R1 és A1 közötti nyíl jelzi), és az R2 erőforrás zárolását kérte (ezt a T1-ről R2-re mutató nyíl jelzi).
A T2 tevékenység zárolta az R2 erőforrást (ezt az R2 és A2 közötti nyíl jelzi), és az R1 erőforrás zárolását kérte (ezt a T2-ről R1-re mutató nyíl jelzi).
Mivel egyik tevékenység sem folytatható, amíg egy erőforrás el nem érhető, és egyik erőforrás sem nyitható fel, amíg egy tevékenység nem folytatódik, holtpont állapot áll fenn.
Note
Az adatbázismotor automatikusan észleli a holtpont ciklusait. Az egyik tranzakciót holtpont áldozataként választja ki, és egy hiba révén megszakítja a tranzakciót a holtpont feloldása érdekében.
Holtpontra képes erőforrások
Előfordulhat, hogy minden felhasználói munkamenetben egy vagy több feladat fut a nevében, ahol az egyes tevékenységek erőforrásokat szerezhetnek be vagy várhatnak az erőforrások beszerzésére. Az alábbi típusú erőforrások blokkolást okozhatnak, ami holtponthoz vezethet.
Locks. Az erőforrások, például objektumok, lapok, sorok, metaadatok és alkalmazások zárolásának beszerzésére való várakozás holtpontot okozhat. A T1 tranzakció például megosztott (
S) zárolással rendelkezik az r1 sorban, és arra vár, hogy kizárólagos (X) zárolást kapjon az r2-n. A T2 tranzakció megosztott (S) zárolással rendelkezik az r2-n, és arra vár, hogy exkluzív (X) zárolást kapjon az r1 sorra. Ez egy zárolási ciklust eredményez, amelyben a T1 és a T2 megvárja, amíg egymás felszabadítják a zárolt erőforrásokat.Feldolgozói szálak. Az elérhető munkaszálra váró várólistás tevékenység holtpontot okozhat. Ha a várakoztatott feladat olyan erőforrásokat birtokol, amelyek blokkolják az összes munkavégző szálat, az holtpontot eredményez. Az S1 munkamenet például elindít egy tranzakciót, és beolvas egy megosztott (
S) zárolást az r1 sorra, majd alvó állapotba kerül. Az összes elérhető feldolgozószálon futó aktív munkamenetek kizárólagos (X) zárolásokat próbálnak beszerezni az r1 sorra. Mivel az S1 munkamenet nem tud munkaszálat beszerezni, nem tudja véglegesíteni a tranzakciót, és nem tudja feloldani a zárolást az r1 sorban. Ez holtpontot eredményez.Memory. Ha egyidejű kérések várnak olyan memóriakivételekre, amelyek nem felelnek meg a rendelkezésre álló memóriának, holtpont léphet fel. Két egyidejű lekérdezés, az 1. és a 2. negyedév például felhasználó által definiált függvényként fut, amelyek 10 MB, illetve 20 MB memóriát szereznek be. Ha minden lekérdezésnek 30 MB-ra van szüksége, és a teljes rendelkezésre álló memória 20 MB, akkor az 1. és a 2. negyedévnek várnia kell, amíg egymás felszabadítják a memóriát, ami holtpontot eredményez.
Párhuzamos lekérdezésvégrehajtással kapcsolatos erőforrások. Az exchange-porthoz társított koordinátorok, előállítók vagy fogyasztói szálak blokkolhatják egymást, és általában holtpontot okozhatnak, ha legalább egy olyan folyamatot is belefoglalnak, amely nem része a párhuzamos lekérdezésnek. A párhuzamos lekérdezések végrehajtásakor az adatbázismotor határozza meg a párhuzamosság mértékét és a szükséges munkaszálak számát az aktuális számítási feladat alapján. Ha a rendszer számítási feladatai váratlanul megváltoznak, például amikor új lekérdezések futnak a kiszolgálón, vagy a rendszer elfogy a feldolgozó szálakból, akkor holtpont léphet fel.
Több aktív eredményhalmaz (MARS) erőforrás. Ezek az erőforrások a MARS alatt a több aktív kérés áthúzásának szabályozására szolgálnak. További információ: Több aktív eredményhalmaz (MARS) használata natív SQL Server-ügyfélalkalmazásban.
Felhasználói erőforrás. Ha egy szál olyan erőforrásra vár, amelyet egy felhasználói alkalmazás esetleg szabályozhat, az erőforrás külső vagy felhasználói erőforrásnak minősül, és zárolásként lesz kezelve.
Munkamenet-zár. Az egy munkamenetben futó tevékenységek egymásba vannak osztva, ami azt jelenti, hogy egy adott időpontban csak egy tevékenység futtatható a munkamenet alatt. Mielőtt a feladat lefutna, kizárólagos hozzáféréssel kell rendelkeznie a session mutexhez.
Tranzakció mutex. Az egy tranzakcióban futó összes tevékenység össze van osztva, ami azt jelenti, hogy egy adott időpontban csak egy tevékenység futtatható a tranzakció alatt. Mielőtt a feladat végrehajtható lenne, kizárólagos hozzáféréssel kell rendelkeznie a tranzakciós mutexhez.
Ahhoz, hogy egy feladat a MARS alatt fusson, be kell szereznie a munkamenet-mutexet. Amennyiben a feladat egy tranzakció keretében fut, meg kell szereznie a tranzakciós mutext. Ez garantálja, hogy egyszerre csak egy tevékenység aktív egy adott munkamenetben és egy adott tranzakcióban. A szükséges mutexek beszerzése után a feladat végrehajtható. Amikor a tevékenység befejeződik, vagy a kérés közepén hozamot ad, először felszabadítja a tranzakciós mutexet, majd a munkamenet-mutexet, fordított beszerzési sorrendben. Ezekkel az erőforrásokkal azonban holtpontok léphetnek fel. Az alábbi pszeudokódban két feladat, az U1 felhasználói kérelem és a felhasználói kérelem U2 fut ugyanabban a munkamenetben.
U1: Rs1=Command1.Execute("insert sometable EXEC usp_someproc"); U2: Rs2=Command2.Execute("select colA from sometable");Az U1 felhasználói kérésből végrehajtott tárolt eljárás megszerezte a munkamenet-mutexet. Ha a tárolt eljárás végrehajtása hosszú időt vesz igénybe, az adatbázismotor feltételezi, hogy a tárolt eljárás a felhasználótól érkező bemenetre vár. A felhasználói kérelem U2 a munkamenet-mutexre vár, míg a felhasználó a U2 eredményhalmazára vár, a U1 pedig egy felhasználói erőforrásra vár. Ez a holtpont állapota logikusan a következőképpen van szemléltetve:
Holtpontok akkor is előfordulhatnak, ha egy táblát particionálnak, és a LOCK_ESCALATION beállítás ALTER TABLE értéke AUTO-ra van állítva. Ha LOCK_ESCALATION be van állítva AUTO, az egyidejűség nő azáltal, hogy lehetővé teszi az adatbázismotor számára a táblapartíciók HoBT-szinten való zárolását a táblaszint helyett. Ha azonban a különálló tranzakciók partíciózárakat tartanak egy táblában, és zárolást akarnak a másik tranzakció partícióján, ez holtpontot okoz. Az ilyen típusú holtpont elkerülhető a következő beállítással LOCK_ESCALATIONTABLE: . Ez a beállítás azonban csökkenti az egyidejűséget azáltal, hogy nagy frissítéseket kényszerít egy partícióra, hogy megvárja a táblazárolást.
Holtpont észlelése
A Holtpontot okozható erőforrások szakaszban felsorolt minden erőforrás részt vesz az adatbázismotor holtpontészlelési sémájában. A holtpont észlelését egy zárolásfigyelő szál végzi, amely rendszeres időközönként keresést indít az adatbázismotor egy példányában található összes feladaton. A következő pontok a keresési folyamatot írják le:
Az alapértelmezett időköz 5 másodperc.
Ha a zárolásfigyelő szál holtpontot talál, a holtpont észlelési időköze a holtpontok gyakoriságától függően 5 másodpercről 100 ezredmásodpercre csökken.
Ha a zárolásfigyelő szál nem talál holtpontot, az adatbázismotor 5 másodpercre növeli a keresések közötti időközöket.
Holtpont észlelése esetén a rendszer feltételezi, hogy a zárolásra váró új szálak belépnek a holtpont ciklusába. Az első néhány zárolási várakozás a holtpont észlelése után azonnal aktiválja a holtpont keresését ahelyett, hogy megvárja a következő holtpont-észlelési időközt. Ha például az aktuális időköz 5 másodperc, és egy holtpontot észlelt, a következő zárolási várakozás azonnal elindítja a holtpont-érzékelőt. Ha ez a zárolási várakozás egy holtpont része, a rendszer azonnal észleli, nem pedig a következő holtpont-keresés során.
Az adatbázismotor általában csak időszakos holtpont-észlelést végez. Mivel a rendszerben előforduló holtpontok száma általában kicsi, az időszakos holtpont-észlelés segít csökkenteni a holtpont-észlelés többletterhelését a rendszerben.
Amikor a zárolásfigyelő holtpontot keres egy adott szálon, azonosítja azt az erőforrást, amelyre a szál várakozik. A zárolási figyelő ezután megkeresi az adott erőforrás tulajdonosait, és rekurzív módon folytatja a holtpont keresését ezekre a szálakra, amíg nem talál egy ciklust. Az ilyen módon azonosított ciklus holtpontot képez.
A holtpont észlelése után az adatbázismotor a holtpontot úgy zárja le, hogy az egyik szálat holtpontként választja ki. Az adatbázismotor a szál által végrehajtott aktuális köteget leállítja, visszaállítja a holtpont miatt érintett áldozat tranzakcióját, és 1205-ös hibakódot ad vissza az alkalmazásnak. A holtpont áldozat tranzakciójának visszaállítása felszabadítja a tranzakció által birtokolt összes zárolást. Ez lehetővé teszi a többi szál tranzakcióinak letiltását és folytatását. Az 1205-ös hiba (holtpont áldozata) a holtpontba került erőforrások típusával kapcsolatos információkat rögzíti.
Alapértelmezés szerint az adatbázismotor azt a tranzakciót választja ki holtpont áldozataként, amelynek visszavonása a legkevésbé költséges. Másik lehetőségként a felhasználó az utasítással SET DEADLOCK_PRIORITY megadhatja a munkamenetek prioritását holtponti helyzetben.
DEADLOCK_PRIORITY beállítható LOW, NORMAL vagy HIGH értékre, továbbá beállítható bármely egész értékre -10 és 10 között. Bizonyos esetekben az adatbázismotor dönthet úgy, hogy rövid időre módosítja a holtpont prioritását a jobb egyidejűség érdekében.
A holtpont alapértelmezett értéke NORMAL, vagyis 0. Ha két munkamenet eltérő holtpont-prioritással rendelkezik, akkor az alacsonyabb prioritású munkamenet tranzakciója lesz a holtpont áldozata. Ha mindkét munkamenet azonos holtpont-prioritással rendelkezik, akkor azt a tranzakciót választják ki, amelyiknek a visszagörgetése a legkevésbé költséges. Ha a holtpont ciklusban részt vevő munkamenetek azonos holtpont prioritással és költséggel rendelkeznek, a program véletlenszerűen választ ki egy áldozatot. A visszagördülő feladat nem választható holtpont áldozataként.
A közös nyelvi futtatókörnyezet (CLR) használatakor a holtpontfigyelő automatikusan észleli a felügyelt eljárásokban elért szinkronizálási erőforrások (monitorok, olvasó-/írózár és szálillesztés) holtpontjait. A holtpontot azonban úgy oldja meg, hogy kivételt ad a holtpont áldozatának kiválasztott eljárásban. Fontos tisztában lenni azzal, hogy a kivétel nem oldja fel automatikusan az áldozat tulajdonában lévő erőforrásokat; az erőforrásokat explicit módon kell felszabadítani. A kivétel viselkedésével összhangban a holtpont áldozatának azonosítására használt kivétel elkapható, és figyelmen kívül hagyható.
Holtpont információs eszközök
A holtpont információinak megtekintéséhez az adatbázismotor monitorozási eszközöket biztosít kiterjesztett xml_deadlock_report esemény, két nyomkövetési jelző és az SQL Profiler holtpont gráfeseménye formájában.
A xml_deadlock_report kiterjesztett esemény a holtpont adatainak rögzítésére javasolt módszer.
Holtpont kiterjesztett esemény
Az SQL Server 2012 (11.x) és újabb verzióiban a xml_deadlock_report kiterjesztett eseményt kell használni az SQL Trace vagy az SQL Profiler holtponti gráfeseményosztálya helyett.
Az system_health esemény-munkamenet alapértelmezés szerint rögzíti az xml_deadlock_report eseményeket. Ezek az események a holtpont gráfot tartalmazzák. Mivel a system_health munkamenet alapértelmezés szerint engedélyezve van, nem kell külön esemény munkamenetet konfigurálnia a holtpont adatainak rögzítéséhez.
A holtpontgráf jellemzően három különböző csomópontból áll:
-
victim-list. A holtponti áldozat folyamatazonosítója. -
process-list. Információ a holtponthoz kapcsolódó összes folyamatról. -
resource-list. Információ a holtponthoz kapcsolódó erőforrásokról.
A munkamenet céladatait a event_filesystem_health Management Studióban tekintheti meg. Ha bármilyen xml_deadlock_report esemény történt, a Management Studio grafikusan ábrázolja a holtpontban lévő feladatokat és erőforrásokat, ahogyan az alábbi példában látható:
A következő lekérdezés megtekintheti az ring_buffer cél által a system_health munkamenet során rögzített összes holtponti eseményt:
SELECT xdr.value('@timestamp', 'datetime') AS deadlock_time,
xdr.query('.') AS event_data
FROM (SELECT CAST ([target_data] AS XML) AS target_data
FROM sys.dm_xe_session_targets AS xt
INNER JOIN sys.dm_xe_sessions AS xs
ON xs.address = xt.event_session_address
WHERE xs.name = N'system_health'
AND xt.target_name = N'ring_buffer') AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(xdr)
ORDER BY deadlock_time DESC;
Itt van az eredmények összessége.
Az alábbi példa a event_data oszlop kimenetére mutat példát:
<event name="xml_deadlock_report" package="sqlserver" timestamp="2022-02-18T08:26:24.698Z">
<data name="xml_report">
<type name="xml" package="package0" />
<value>
<deadlock>
<victim-list>
<victimProcess id="process27b9b0b9848" />
</victim-list>
<process-list>
<process id="process27b9b0b9848" taskpriority="0" logused="0" waitresource="KEY: 5:72057594214350848 (1a39e6095155)" waittime="1631" ownerId="11088595" transactionname="SELECT" lasttranstarted="2022-02-18T00:26:23.073" XDES="0x27b9f79fac0" lockMode="S" schedulerid="9" kpid="15336" status="suspended" spid="62" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2022-02-18T00:26:22.893" lastbatchcompleted="2022-02-18T00:26:22.890" lastattention="1900-01-01T00:00:00.890" clientapp="SQLCMD" hostname="ContosoServer" hostpid="7908" loginname="CONTOSO\user" isolationlevel="read committed (2)" xactid="11088595" currentdb="5" lockTimeout="4294967295" clientoption1="538968096" clientoption2="128056">
<executionStack>
<frame procname="AdventureWorks2022.dbo.p1" line="3" stmtstart="78" stmtend="180" sqlhandle="0x0300050020766505ca3e07008ba8000001000000000000000000000000000000000000000000000000000000">
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+ </frame>
<frame procname="adhoc" line="4" stmtstart="82" stmtend="98" sqlhandle="0x020000006263ec01ebb919c335024a072a2699958d3fcce60000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
SET NOCOUNT ON
WHILE (1=1)
BEGIN
EXEC p1 4
END
</inputbuf>
</process>
<process id="process27b9ee33c28" taskpriority="0" logused="252" waitresource="KEY: 5:72057594214416384 (e5b3d7e750dd)" waittime="1631" ownerId="11088593" transactionname="UPDATE" lasttranstarted="2022-02-18T00:26:23.073" XDES="0x27ba15a4490" lockMode="X" schedulerid="6" kpid="5584" status="suspended" spid="58" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-02-18T00:26:22.890" lastbatchcompleted="2022-02-18T00:26:22.890" lastattention="1900-01-01T00:00:00.890" clientapp="SQLCMD" hostname="ContosoServer" hostpid="15316" loginname="CONTOSO\user" isolationlevel="read committed (2)" xactid="11088593" currentdb="5" lockTimeout="4294967295" clientoption1="538968096" clientoption2="128056">
<executionStack>
<frame procname="AdventureWorks2022.dbo.p2" line="3" stmtstart="76" stmtend="150" sqlhandle="0x03000500599a5906ce3e07008ba8000001000000000000000000000000000000000000000000000000000000">
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p </frame>
<frame procname="adhoc" line="4" stmtstart="82" stmtend="98" sqlhandle="0x02000000008fe521e5fb1099410048c5743ff7da04b2047b0000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
SET NOCOUNT ON
WHILE (1=1)
BEGIN
EXEC p2 4
END
</inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594214350848" dbid="5" objectname="AdventureWorks2022.dbo.t1" indexname="cidx" id="lock27b9dd26a00" mode="X" associatedObjectId="72057594214350848">
<owner-list>
<owner id="process27b9ee33c28" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process27b9b0b9848" mode="S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594214416384" dbid="5" objectname="AdventureWorks2022.dbo.t1" indexname="idx1" id="lock27afa392600" mode="S" associatedObjectId="72057594214416384">
<owner-list>
<owner id="process27b9b0b9848" mode="S" />
</owner-list>
<waiter-list>
<waiter id="process27b9ee33c28" mode="X" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</value>
</data>
</event>
Nyomkövetési jelző 1204 és nyomkövetési jelző 1222
Holtpontok esetén, és ha a 1204-es vagy 1222-es nyomkövetési jelző engedélyezve van, a holtpont részletei megjelennek az SQL Server hibanaplójában. A nyomkövetési jelző 1204 a holtpontban részt vevő csomópontok által formázott holtpont-információkat jelenti. A nyomkövetési jelző 1222 a holtpont adatait formázza, először folyamatok, majd erőforrások szerint. Mindkét nyomkövetési jelző lehetővé teszi ugyanannak a holtpont eseménynek a két ábrázolását.
Important
Ne használjon 1204-et és 1222-et a munkaterhelés-igényes rendszereken, amelyek holtpontot tapasztalnak. A nyomkövetési jelzők használata teljesítményproblémákat eredményezhet. Ehelyett használja a Deadlock kiterjesztett eseményt a szükséges információk rögzítéséhez.
Az 1204-ben és 1222-ben használt nyomkövetési jelzők tulajdonságainak meghatározása mellett az alábbi táblázat a hasonlóságokat és a különbségeket is megjeleníti.
| Property | Nyomkövetési jelző 1204 és nyomkövetési jelző 1222 | Nyomkövetési jelző csak 1204 | 1222 nyomkövetési jelző csak |
|---|---|---|---|
| Kimeneti formátum | A kimenetet az SQL Server hibanaplója rögzíti. | A holtpontban lévő csomópontokra összpontosított. Minden csomópont rendelkezik egy dedikált szakaszsal, az utolsó szakasz pedig a holtpont áldozatát ismerteti. | Olyan XML-szerű adatokat ad vissza, amelyek nem felelnek meg az XML-sémadefiníciós (XSD) sémának. A formátum három fő szakaszból áll. Az első szakasz meghatározza a holtpont áldozatát. A második szakasz a holtpontban lévő összes folyamatot ismerteti. A harmadik szakasz azokat az erőforrásokat ismerteti, amelyek az 1204-es nyomkövetési jelző csomópontjaival szinonimák. |
| Attribútumok azonosítása |
SPID:<x> ECID:<x>. Azonosítja a munkamenet-azonosító szálat párhuzamos folyamatok esetén. A bejegyzés SPID:<x> ECID:0– ahol <x> a SPID érték helyébe lép – a fő szálat jelöli. A bejegyzés SPID:<x> ECID:<y>, ahol <x> a SPID érték helyébe lép, és <y> nagyobb, mint 0, ugyanahhoz az SPID-hez tartozó végrehajtási környezetet jelöli.BatchID (sbid a nyomkövetési jelző 1222-ben). Azonosítja azt a köteget, amelyből a kód végrehajtása zárolást kér vagy tart. Ha több aktív eredményhalmaz (MARS) le van tiltva, a BatchID értéke 0. Ha a MARS engedélyezve van, az aktív kötegek értéke 1– n. Ha a munkamenetben nincsenek aktív kötegek, a BatchID 0.Mode Megadja egy adott erőforrás zárolásának típusát, amelyet egy szál kér, ad meg vagy vár. A mód lehet szándékos megosztás (IS), megosztott (S), frissítés (U), kizárólagos szándék (IX), megosztott kizárólagos szándékkal (SIX) és kizárólagos (X).Line # (line a nyomkövetési jelző 1222-ben). A holtpont bekövetkezésekor végrehajtott utasítások aktuális kötegében szereplő sorszámot sorolja fel.Input Buf (inputbuf a nyomkövetési jelző 1222-ben). Az aktuális csomag összes utasítását listázza. |
Node A holtpontlánc bejegyzésszámát jelöli.Lists A zárolás tulajdonosa lehet része ezeknek a listáknak:Grant List Az erőforrás aktuális tulajdonosainak számbavétele.Convert List Felsorolja azokat a jelenlegi tulajdonosokat, akik a zárukat magasabb szintre próbálják átalakítani.Wait List Az erőforrás aktuális új zárolási kérelmeinek számbavétele.Statement TypeAzt az utasítástípust (SELECT, vagy INSERTUPDATE) írja le, DELETEamelyre a szálak rendelkeznek engedélyekkel.Victim Resource Owner Megadja azt a részt vevő szálat, amelyet az adatbázismotor áldozatként választ a holtponti ciklus megszakítására. A kiválasztott szál és annak összes végrehajtási környezete leáll.Next Branch A holtpont ciklusban részt vevő spidből származó két vagy több végrehajtási környezetet jelöli. |
deadlock victim A holtpontként kiválasztott feladat (lásd sys.dm_os_tasks) fizikai memóriacímét jelöli. Megoldatlan holtpont esetén az érték nulla lehet.executionstack A holtpont bekövetkezésekor végrehajtott Transact-SQL hívásverem.priority Holtpont-prioritást jelöl.logused A feladat által felhasznált naplótárhely.owner id A kérést vezérlő tranzakció azonosítója.status A tevékenység állapota. További információ: sys.dm_os_tasks.waitresource A tevékenységhez szükséges erőforrás.waittime Az erőforrásra váró idő ezredmásodpercben.schedulerid A tevékenységhez társított ütemező. Lásd : sys.dm_os_schedulers.hostname A munkaállomás neve.isolationlevel Az aktuális tranzakcióelkülönítési szint.Xactid A kérést vezérlő tranzakció azonosítója.currentdb Az adatbázis azonosítója.lastbatchstarted A legutóbbi alkalom, amikor az ügyfélfolyamat elindította a kötegelt végrehajtást.lastbatchcompleted Amikor az ügyfélfolyamat legutóbb befejezte a köteg végrehajtását.clientoption1 és clientoption2 beállítják a munkamenet opcióit. Ezek az értékek olyan bitmaszkok, amelyek általában az olyan utasítások által SET szabályozott beállításokat jelölik, mint az SET NOCOUNT és SET XACTABORTa . További információ: @@OPTIONS.associatedObjectId A HoBT (halom vagy B-fa) azonosítóját jelöli. |
| Erőforrás attribútumai |
RID azonosítja a táblán belüli egyetlen sort, amelyen zárolást tartanak vagy kérnek. A RID így jelenik meg: db_id:file_id:page_no:row_no. Például: RID: 6:1:20789:0.OBJECT azonosítja a táblát, amelyen a zárolást tartják vagy kérik.
OBJECT a a következőképpen jelenik meg OBJECT: db_id:object_id: Például: TAB: 6:2009058193.KEY Azonosítja azt a kulcstartományt egy indexen belül, amelyen zárolást tartanak vagy kérnek. A KEY kulcsként jelenik meg: db_id:hobt_id (indexkulcs kivonat értéke). Például: KEY: 6:72057594057457664 (350007a4d329).PAG Azonosítja a lapforrást, amelynek a zárolása folyamatban van vagy kérik.
PAG a a következőképpen jelenik meg PAG: db_id:file_id:page_no: Például: PAG: 6:1:20789.EXT Azonosítja a kiterjedés struktúráját.
EXT a a következőképpen jelenik meg EXT: db_id:file_id:extent_no: Például: EXT: 6:1:9.DB Azonosítja az adatbázis zárolását.
DB az alábbi módok egyikével jelenik meg:DB: db_idDB: db_id[BULK-OP-DB], amely azonosítja az adatbázis biztonsági mentése által létrehozott adatbázis-zárolást.DB: db_id[BULK-OP-LOG], amely azonosítja a naplómentés során alkalmazott zárolást.APP Alkalmazás-zárat azonosít.
APP a a következőképpen jelenik meg APP: lock_resource: Például: APP: Formf370f478.METADATA A holtpontban lévő metaadat-erőforrásokat jelöli. Mivel METADATA sok alforrás van, a visszaadott érték a holtpontot tartalmazó alforrástól függ. Például METADATA.USER_TYPEuser_type_id = *integer_value*ad vissza. További információ az erőforrásokról METADATA és az alforrásokról: sys.dm_tran_locks.HOBT Egy holtpontban lévő halom vagy B-fa. |
Ez a nyomkövetési jelző semmilyen egyedi sajátossággal nem rendelkezik. | Ez a nyomkövetési jelző semmilyen egyedi sajátossággal nem rendelkezik. |
Nyomkövetési jelző 1204-példa
Az alábbi példa az 1204-ben bekapcsolva lévő nyomkövetési jelző kimenetét mutatja be. Ebben az esetben az 1. csomópont táblája egy index nélküli halom, a 2. csomópontban pedig egy halom, amely nem rendezett indexet tartalmaz. A 2. csomópont indexkulcsa a holtpont bekövetkezésekor frissül.
Deadlock encountered .... Printing deadlock information
Wait-for graph
Node:1
RID: 6:1:20789:0 CleanCnt:3 Mode:X Flags: 0x2
Grant List 0:
Owner:0x0315D6A0 Mode: X
Flg:0x0 Ref:0 Life:02000000 SPID:55 ECID:0 XactLockInfo: 0x04D9E27C
SPID: 55 ECID: 0 Statement Type: UPDATE Line #: 6
Input Buf: Language Event:
BEGIN TRANSACTION
EXEC usp_p2
Requested By:
ResType:LockOwner Stype:'OR'Xdes:0x03A3DAD0
Mode: U SPID:54 BatchID:0 ECID:0 TaskProxy:(0x04976374) Value:0x315d200 Cost:(0/868)
Node:2
KEY: 6:72057594057457664 (350007a4d329) CleanCnt:2 Mode:X Flags: 0x0
Grant List 0:
Owner:0x0315D140 Mode: X
Flg:0x0 Ref:0 Life:02000000 SPID:54 ECID:0 XactLockInfo: 0x03A3DAF4
SPID: 54 ECID: 0 Statement Type: UPDATE Line #: 6
Input Buf: Language Event:
BEGIN TRANSACTION
EXEC usp_p1
Requested By:
ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0 Cost:(0/380)
Victim Resource Owner:
ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0 Cost:(0/380)
Nyomkövetési jelző 1222-példa
Az alábbi példa az 1222-ben bekapcsolt nyomkövetési jelző kimenetét mutatja. Ebben az esetben az egyik tábla egy index nélküli halom, a másik pedig egy halom, amely nem rendezett indexet tartalmaz. A második táblázatban az indexkulcs frissül a holtpont bekövetkezésekor.
deadlock-list
deadlock victim=process689978
process-list
process id=process6891f8 taskpriority=0 logused=868
waitresource=RID: 6:1:20789:0 waittime=1359 ownerId=310444
transactionname=user_transaction
lasttranstarted=2022-02-05T11:22:42.733 XDES=0x3a3dad0
lockMode=U schedulerid=1 kpid=1952 status=suspended spid=54
sbid=0 ecid=0 priority=0 transcount=2
lastbatchstarted=2022-02-05T11:22:42.733
lastbatchcompleted=2022-02-05T11:22:42.733
clientapp=Microsoft SQL Server Management Studio - Query
hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
isolationlevel=read committed (2) xactid=310444 currentdb=6
lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
executionStack
frame procname=AdventureWorks2022.dbo.usp_p1 line=6 stmtstart=202
sqlhandle=0x0300060013e6446b027cbb00c69600000100000000000000
UPDATE T2 SET COL1 = 3 WHERE COL1 = 1;
frame procname=adhoc line=3 stmtstart=44
sqlhandle=0x01000600856aa70f503b8104000000000000000000000000
EXEC usp_p1
inputbuf
BEGIN TRANSACTION
EXEC usp_p1
process id=process689978 taskpriority=0 logused=380
waitresource=KEY: 6:72057594057457664 (350007a4d329)
waittime=5015 ownerId=310462 transactionname=user_transaction
lasttranstarted=2022-02-05T11:22:44.077 XDES=0x4d9e258 lockMode=U
schedulerid=1 kpid=3024 status=suspended spid=55 sbid=0 ecid=0
priority=0 transcount=2 lastbatchstarted=2022-02-05T11:22:44.077
lastbatchcompleted=2022-02-05T11:22:44.077
clientapp=Microsoft SQL Server Management Studio - Query
hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
isolationlevel=read committed (2) xactid=310462 currentdb=6
lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
executionStack
frame procname=AdventureWorks2022.dbo.usp_p2 line=6 stmtstart=200
sqlhandle=0x030006004c0a396c027cbb00c69600000100000000000000
UPDATE T1 SET COL1 = 4 WHERE COL1 = 1;
frame procname=adhoc line=3 stmtstart=44
sqlhandle=0x01000600d688e709b85f8904000000000000000000000000
EXEC usp_p2
inputbuf
BEGIN TRANSACTION
EXEC usp_p2
resource-list
ridlock fileid=1 pageid=20789 dbid=6 objectname=AdventureWorks2022.dbo.T2
id=lock3136940 mode=X associatedObjectId=72057594057392128
owner-list
owner id=process689978 mode=X
waiter-list
waiter id=process6891f8 mode=U requestType=wait
keylock hobtid=72057594057457664 dbid=6 objectname=AdventureWorks2022.dbo.T1
indexname=nci_T1_COL1 id=lock3136fc0 mode=X
associatedObjectId=72057594057457664
owner-list
owner id=process6891f8 mode=X
waiter-list
waiter id=process689978 mode=U requestType=wait
Profiler holtpontábrázolás esemény
Az SQL Profiler olyan eseményt jelenít meg, amely grafikusan ábrázolja a holtponthoz tartozó feladatokat és erőforrásokat. Az alábbi példa az SQL Profiler kimenetét mutatja be, amikor a holtpont gráfesemény be van kapcsolva.
Az SQL Profiler és az SQL Trace funkciói elavultak, és kiterjesztett események váltják fel. A kiterjesztett események teljesítményterhelése kisebb, és konfigurálhatóbb, mint az SQL Trace. Fontolja meg a Kiterjesztett események holtpont esemény használatát az SQL Profiler holtpontok nyomon követése helyett.
További információ a holtpont eseményről: Lock:Deadlock Event Class. Az SQL Profiler holtpont-gráfjairól további információt a Holtpontdiagramok mentése (SQL Server Profiler) című témakörben talál.
A kiterjesztett események az SQL Trace eseményosztályainak megfelelőit biztosítják. További információ : Az SQL Trace eseményosztályokkal egyenértékű kiterjesztett események megtekintése. A kiterjesztett események használata ajánlott az SQL Trace helyett.
Holtpontok kezelése
Amikor az adatbázismotor egy példánya holtpontként választ ki egy tranzakciót, az leállítja az aktuális köteget, visszaállítja a tranzakciót, és visszaadja az 1205-ös hibát az alkalmazásnak. A visszaadott üzenet a következőképpen van strukturálva:
Your transaction (process ID #...) was deadlocked on {lock | communication buffer | thread} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.
Mivel a Transact-SQL lekérdezéseket beküldő alkalmazások kiválaszthatók holtpont áldozataként, az alkalmazásoknak olyan hibakezelőt kell használniuk, amely képes kezelni az 1205-ös hibát. Ha egy alkalmazás nem kezeli a hibát, az alkalmazás nem tudhatja, hogy a tranzakció vissza lett állítva.
Az 1205-ös hibát észlelő hibakezelő implementálása lehetővé teszi az alkalmazások számára a holtpontok kezelését és a javítási műveletek végrehajtását (például a holtponton lévő lekérdezés automatikus újraküldését).
Az alkalmazásnak rövid időre szüneteltetnie kell a működést a lekérdezés újbóli elküldése előtt. Ez lehetőséget ad a holtpontban részt vevő többi tranzakciónak a zárolások befejezésére és feloldására. A szüneteltetés időtartamának véletlenszerűvé alakítása minimálisra csökkenti annak valószínűségét, hogy a holtpont ismétlődik, amikor az újraküldett lekérdezés kéri a zárolását. Előfordulhat például, hogy a hibakezelőt úgy kódoljuk, hogy egy és három másodperc közötti véletlenszerű időtartamra szüneteljen.
Kezelés TRY...CATCH használatával
A TRY...CATCH utasítást használhatja a holtpontok kezeléséhez. Az 1205-ös hibát a CATCH blokk észlelheti.
További információ: Holtpontok kezelése.
Holtpontok minimalizálása
Bár a holtpontok nem kerülhetők el teljesen, bizonyos programozási szabályokat betartva minimalizálható a holtpontok előfordulásának esélye. A holtpontok számának minimalizálása növelheti a tranzakciók átviteli sebességét, és csökkentheti a rendszer terhelését, mivel kevesebb tranzakció lesz:
- Visszaállítva, visszavonva a tranzakció által végzett összes munkát.
- Újraküldve az alkalmazások által, mert a holtpontnál vissza lettek állítva.
A holtpontok minimalizálása érdekében:
- Ugyanabban a sorrendben érje el az objektumokat.
- Kerülje a felhasználói beavatkozást a tranzakciókban.
- A tranzakciók legyenek rövidek, és legyenek egy kötegben.
- Kerülje a magasabb elkülönítési szinteket, például
REPEATABLE READésSERIALIZABLEha nem szükséges. - Használjon sor-verziókezelésen alapuló elkülönítési szintet.
- Engedélyezze az
READ_COMMITTED_SNAPSHOTadatbázis-beállítás számára, hogy sorverziót használjon a tranzakciókhoz az elkülönítésiREAD COMMITTEDszint használatával. - Tranzakciók pillanatkép-elkülönítésének használata.
- Engedélyezze az
- Használja a kötött kapcsolatokat.
Objektumok elérése ugyanabban a sorrendben
Ha minden egyidejű tranzakció ugyanabban a sorrendben fér hozzá az objektumokhoz, akkor a holtpontok kisebb valószínűséggel fordulnak elő. Ha például két egyidejű tranzakció zárolja a Supplier táblát, majd a Part táblában, az egyik tranzakció le lesz tiltva a Supplier táblában, amíg a másik tranzakció be nem fejeződik. Az első tranzakció véglegesítése vagy visszaállítása után a második folytatódik, és nem történik holtpont. A tárolt eljárások használata az összes adatmódosítás esetében szabványosíthatja az objektumok elérésének sorrendjét.
A tranzakciók felhasználói beavatkozásának elkerülése
Kerülje a felhasználói beavatkozást tartalmazó tranzakciókat, mert a felhasználói beavatkozás nélkül futó kötegek sebessége sokkal gyorsabb, mint az a sebesség, amikor a felhasználónak manuálisan kell válaszolnia a lekérdezésekre, például egy alkalmazás által kért paraméter kérésére válaszol. Ez csökkenti a rendszer átviteli sebességét, mert a tranzakció által lekötött zárolások csak a tranzakció véglegesítésekor vagy visszaállításakor szabadulnak fel. Még ha nem is történik holtpont, az ugyanahhoz az erőforráshoz hozzáférő egyéb tranzakciók is le lesznek tiltva, miközben a tranzakció befejezésére várnak.
Tranzakciók rövid és egy kötegben tartása
Holtpontok általában akkor fordulnak elő, ha több hosszú ideig futó tranzakció végrehajtása történik egyszerre ugyanabban az adatbázisban. Minél hosszabb a tranzakció, annál hosszabb a kizárólagos vagy frissítési zárolás, blokkolja a többi tevékenységet, és lehetséges holtponthoz vezet.
A tranzakciók egy kötegben tartása minimálisra csökkenti a hálózati kerekítéseket egy tranzakció során, így csökken a tranzakció ügyfélfeldolgozás miatti késése.
Kerülje a magasabb elkülönítési szinteket
Annak meghatározása, hogy egy tranzakció alacsonyabb elkülönítési szinten futtatható-e.
READ COMMITTED használata lehetővé teszi, hogy egy tranzakció beolvassa a korábban beolvasott (de nem módosított) adatokat egy másik tranzakcióval anélkül, hogy megvárja a tranzakció befejezését.
READ COMMITTED a megosztott zárolásokat rövidebb ideig tárolja, mint egy magasabb elkülönítési szint, például SERIALIZABLE. Ez csökkenti a zárolási ütközést.
Sorverzióalapú elkülönítési szint használata
Ha az READ_COMMITTED_SNAPSHOT adatbázis-beállítás be van állítva ON, az elkülönítési szinten futó tranzakciók sorverziót READ COMMITTED használnak, nem pedig megosztott zárolásokat az olvasási műveletek során.
Jótanács
A Microsoft minden alkalmazás esetében a sorverzióalapú READ COMMITTED elkülönítési szintet javasolja, kivéve, ha egy alkalmazás a zárolásalapú READ COMMITTED elkülönítési szint blokkolási viselkedésére támaszkodik.
A pillanatkép izoláció szintén sor verziózást használ, ami nem alkalmaz megosztott zárolásokat az olvasási műveletek során. Ahhoz, hogy egy tranzakció pillanatkép-elkülönítéssel fusson, be kell állítani az ALLOW_SNAPSHOT_ISOLATION adatbázis-beállítást ON.
A sorverzió-alapú elkülönítési szintek használatával minimalizálhatja az olvasási és írási műveletek közötti holtpontokat.
Kötött kapcsolatok használata
Kötött kapcsolatok használatával az ugyanazon alkalmazás által megnyitott két vagy több kapcsolat együttműködhet egymással. A másodlagos kapcsolatok által beszerzett zárolások úgy vannak tárolva, mintha az elsődleges kapcsolat szerezte volna be őket, és fordítva. Ezért nem blokkolják egymást.
Holtpont okozása
Előfordulhat, hogy tanulási vagy demonstrációs célokra patthelyzetet kell létrehoznia.
Az alábbi példa a AdventureWorksLT2019 mintaadatbázisban működik az alapértelmezett sémával és adatokkal, ha READ_COMMITTED_SNAPSHOT engedélyezve van. A minta letöltéséhez látogasson el az AdventureWorks mintaadatbázisaiba.
Ha például az optimalizált zárolás engedélyezve van, holtpontot okoz, tekintse meg az Optimalizált zárolás és holtpontok című témakört.
A holtpont létrehozásához két munkamenetet kell csatlakoztatnia a AdventureWorksLT2019 adatbázishoz. Ezeket a munkameneteket A ésB munkamenetként tekintjük. Ezt a két munkamenetet két lekérdezésablak létrehozásával hozhatja létre az SQL Server Management Studióban (SSMS).
Az A munkamenetben futtassa a következő köteget. Ez a kód egy explicit tranzakciót indít el, és végrehajt egy utasítást, amely frissíti a táblát SalesLT.Product . Ehhez a tranzakció egy frissítési (U) zárolást szerez be a tábla SalesLT.Product megfelelő soraiban, amelyeket ezután kizárólagos (X) zárolásokká alakít át. Nyitva hagyjuk a tranzakciót.
BEGIN TRANSACTION;
UPDATE SalesLT.Product
SET SellEndDate = SellEndDate + 1
WHERE Color = 'Red';
Ezután futtassa a következő batch fájlt a B munkamenet során. Ez a kód nem indít el explicit módon tranzakciót. Ehelyett automatikus kiküldéses tranzakciós módban működik. Ez az utasítás frissíti a SalesLT.ProductDescription táblát. A frissítés egy frissítési (U) zárolást használ a SalesLT.ProductDescription tábla megfelelő soraiban. A lekérdezés más táblákhoz csatlakozik, beleértve a SalesLT.Product táblát is.
UPDATE SalesLT.ProductDescription
SET Description = Description
FROM SalesLT.ProductDescription AS pd
INNER JOIN SalesLT.ProductModelProductDescription AS pmpd
ON pd.ProductDescriptionID = pmpd.ProductDescriptionID
INNER JOIN SalesLT.ProductModel AS pm
ON pmpd.ProductModelID = pm.ProductModelID
INNER JOIN SalesLT.Product AS p
ON pm.ProductModelID = p.ProductModelID
WHERE p.Color = 'Silver';
A frissítés végrehajtásához a B munkamenetnek megosztott (S) zárolást kell végeznie a tábla SalesLT.Productsoraiban, beleértve az A munkamenet által zárolt sorokat is. A B munkamenet le van tiltva.SalesLT.Product
Vissza az A munkamenethez. Futtassa a következő UPDATE utasítást. Ez az utasítás a korábban megnyitott tranzakció részeként fut.
UPDATE SalesLT.ProductDescription
SET Description = Description
FROM SalesLT.ProductDescription AS pd
INNER JOIN SalesLT.ProductModelProductDescription AS pmpd
ON pd.ProductDescriptionID = pmpd.ProductDescriptionID
INNER JOIN SalesLT.ProductModel AS pm
ON pmpd.ProductModelID = pm.ProductModelID
INNER JOIN SalesLT.Product AS p
ON pm.ProductModelID = p.ProductModelID
WHERE p.Color = 'Red';
Az A munkamenet második frissítési utasítását a SalesLT.ProductDescription blokkolja.
A munkamenet és B munkamenet most kölcsönösen blokkolják egymást. Egyik tranzakció sem folytatható, mivel mindegyiknek olyan erőforrásra van szüksége, amelyet a másik zárol.
Néhány másodperc elteltével a holtpontmonitor azonosítja, hogy az A. munkamenet és B munkamenetben tranzakciói kölcsönösen blokkolják egymást, és egyik sem tud előrehaladást elérni. Egy holtpontot észlel, az A munkamenet a holtpont áldozataként lett kiválasztva. B munkamenet sikeresen befejeződik. Hibaüzenet jelenik meg az A munkamenet lekérdezési ablakában az alábbi példához hasonló szöveggel:
Msg 1205, Level 13, State 51, Line 7
Transaction (Process ID 51) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Ha nincs holtpont, ellenőrizze, hogy a mintaadatbázisban engedélyezve van-e a READ_COMMITTED_SNAPSHOT. A holtpontok bármilyen adatbázis-konfigurációban előfordulhatnak, de ebben a példában engedélyezni kell a READ_COMMITTED_SNAPSHOT opciót.
A holtpont részleteit az ring_buffer esemény-munkamenet céljában tekintheti meg, amely alapértelmezés szerint engedélyezve és aktív az SQL Serverben és az system_health Azure SQL Managed Instance-ben. Fontolja meg a következő lekérdezést:
WITH cteDeadLocks ([Deadlock_XML])
AS (SELECT CAST (target_data AS XML) AS [Deadlock_XML]
FROM sys.dm_xe_sessions AS xs
INNER JOIN sys.dm_xe_session_targets AS xst
ON xs.[address] = xst.event_session_address
WHERE xs.[name] = 'system_health'
AND xst.target_name = 'ring_buffer')
SELECT x.Graph.query('(event/data/value/deadlock)[1]') AS Deadlock_XML,
x.Graph.value('(event/data/value/deadlock/process-list/process/@lastbatchstarted)[1]', 'datetime2(3)') AS when_occurred,
DB_Name(x.Graph.value('(event/data/value/deadlock/process-list/process/@currentdb)[1]', 'int')) AS DB --Current database of the first listed process
FROM (SELECT Graph.query('.') AS Graph
FROM cteDeadLocks AS c
CROSS APPLY c.[Deadlock_XML].nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS Deadlock_Report(Graph)) AS x
ORDER BY when_occurred DESC;
Az XML-t az Deadlock_XML SSMS oszlopában tekintheti meg, ha kijelöli a hivatkozásként megjelenő cellát. Mentse el a kimenetet mint .xdl fájl, zárja be, majd nyissa meg újra az .xdl fájlt az SSMS-ben a vizuális holtponti gráf megtekintéséhez. A holtpont gráfnak az alábbi képhez hasonlóan kell kinéznie.
Optimalizált zárolás és holtpontok
Optimalizált zárolás esetén az oldal- és sorzárolások csak a tranzakció végéig lesznek megtartva. A sor frissítése után azonnal megjelennek. Továbbá, ha READ_COMMITTED_SNAPSHOT engedélyezve van, a frissítési (U) zárolások nem használatosak. Ennek eredményeképpen csökken a holtpontok valószínűsége.
Az előző példa nem okoz holtpontot, ha az optimalizált zárolás engedélyezve van, mert a frissítési (U) zárolásokra támaszkodik.
Az alábbi példa holtpontot okozhat egy olyan adatbázisban, amelyen az optimalizált zárolás engedélyezve van.
Először hozzon létre egy példatáblát, és adjon hozzá adatokat.
CREATE TABLE t2
(
a INT PRIMARY KEY NOT NULL,
b INT NULL
);
INSERT INTO t2
VALUES (1, 10),
(2, 20),
(3, 30);
A következő T-SQL-kötegek, amelyeket két külön munkamenetben, egymás után hajtanak végre, létrehoznak egy holtpontot.
Az 1. ülés során:
BEGIN TRANSACTION xactA;
UPDATE t2
SET b = b + 10
WHERE a = 1;
A 2. munkamenetben:
BEGIN TRANSACTION xactB;
UPDATE t2
SET b = b + 10
WHERE a = 2;
Az 1. ülés során:
UPDATE t2
SET b = b + 100
WHERE a = 2;
A 2. munkamenetben:
UPDATE t2
SET b = b + 20
WHERE a = 1;
Ebben az esetben minden munkamenet kizárólagos (X) zárolást tartalmaz a saját tranzakcióazonosító (TID) erőforrásán, és a másik TID megosztott (S) zárolására vár, ami holtpontot eredményez.
Az alábbi rövidített holtpont jelentés az optimalizált zárolásra jellemző elemeket és attribútumokat tartalmazza. A blokkolási jelentés <resource-list> alatti minden erőforrásnál minden <xactlock> elem a blokkolás egyes tagjainak mögöttes erőforrásait és TID zárolási adatait jelzi.
<deadlock>
<victim-list>
<victimProcess id="process12994344c58" />
</victim-list>
<process-list>
<process id="process12994344c58" taskpriority="0" logused="272" waitresource="XACT: 23:2476:0 KEY: 23:72057594049593344 (8194443284a0)" waittime="447" ownerId="3234906" transactionname="xactA" lasttranstarted="2025-10-08T21:36:34.063" XDES="0x12984ba0480" lockMode="S" schedulerid="2" kpid="204928" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2025-10-08T21:36:40.857" lastbatchcompleted="2025-10-08T21:36:34.063" lastattention="2025-10-08T21:36:11.340" clientapp="Microsoft SQL Server Management Studio - Query" hostname="WS1" hostpid="23380" loginname="user1" isolationlevel="read committed (2)" xactid="3234906" currentdb="23" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<inputbuf>
UPDATE t2
SET b = b + 20
WHERE a = 1;
</inputbuf>
</process>
<process id="process1299c969828" taskpriority="0" logused="272" waitresource="XACT: 23:2477:0 KEY: 23:72057594049593344 (61a06abd401c)" waittime="3083" ownerId="3234886" transactionname="xactB" lasttranstarted="2025-10-08T21:36:30.303" XDES="0x12995c84480" lockMode="S" schedulerid="2" kpid="63348" status="suspended" spid="88" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2025-10-08T21:36:38.223" lastbatchcompleted="2025-10-08T21:36:30.303" lastattention="1900-01-01T00:00:00.303" clientapp="Microsoft SQL Server Management Studio - Query" hostname="WS1" hostpid="23380" loginname="user1" isolationlevel="read committed (2)" xactid="3234886" currentdb="23" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<inputbuf>
UPDATE t2
SET b = b + 100
WHERE a = 2;
</inputbuf>
</process>
</process-list>
<resource-list>
<xactlock xdesIdLow="2476" xdesIdHigh="0" dbid="23" id="lock1299fa06c00" mode="X">
<UnderlyingResource>
<keylock hobtid="72057594049593344" dbid="23" objectname="e6fc405e-1ee8-49df-a2b3-54ee0151d851.dbo.t2" indexname="PK__t2__3BD0198ED3CBA65E" />
</UnderlyingResource>
<owner-list>
<owner id="process1299c969828" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process12994344c58" mode="S" requestType="wait" />
</waiter-list>
</xactlock>
<xactlock xdesIdLow="2477" xdesIdHigh="0" dbid="23" id="lock129940b2380" mode="X">
<UnderlyingResource>
<keylock hobtid="72057594049593344" dbid="23" objectname="e6fc405e-1ee8-49df-a2b3-54ee0151d851.dbo.t2" indexname="PK__t2__3BD0198ED3CBA65E" />
</UnderlyingResource>
<owner-list>
<owner id="process12994344c58" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process1299c969828" mode="S" requestType="wait" />
</waiter-list>
</xactlock>
</resource-list>
</deadlock>
Kapcsolódó tartalom
- bővített események áttekintése
- sys.dm_tran_locks (Transact-SQL)
- Holtpont gráf eseményosztály
- Holtpontok újraolvasható olvasási szinttel
- Zárolás:Holtpontlánc eseményosztálya
- Zárolás:Holtpont esemény osztálya
- SET DEADLOCK_PRIORITY (Transact-SQL)
- Holtpontok elemzése és megakadályozása az Azure SQL Database-ben és az SQL Database-ben a Fabricben
- Holtpontfájl megnyitása, megtekintése és nyomtatása az SQL Server Management Studióban (SSMS)