Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
platí pro:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Analytics Platform System (PDW)
databáze SQL v Microsoft Fabric
Tento článek podrobně popisuje vzájemné zablokování v databázovém stroji. Mrtvé zámky jsou způsobeny konkurenčními zámky v databázi, často ve vícekrokových transakcích. Další informace o transakcích a zámcích naleznete v Průvodci zamykáním transakcí a verzováním řádků.
Podrobnější informace o identifikaci a prevenci zablokování ve službě Azure SQL Database a databázi SQL v prostředcích infrastruktury najdete v tématu Analýza a zabránění zablokování ve službě Azure SQL Database a databázi SQL v prostředcích infrastruktury.
Pochopit mrtvé zámky
Vzájemné zablokování nastane, když dva nebo více úkolů navzájem trvale blokují tím, že má každý z nich zámek na zdroji, který se ostatní úkoly snaží také uzamknout. Například:
Transakce A získá sdílený zámek na řádku 1.
Transakce B získá sdílený zámek na řádku 2.
Transakce A nyní požaduje výhradní zámek na řádku 2 a je blokována, dokud transakce B nedokončí a neuvolní sdílený zámek, který má na řádku 2.
Transakce B teď požaduje výhradní zámek na řádku 1 a je blokována, dokud transakce A nedokončí svůj proces a neuvolní sdílený zámek, který má na řádku 1.
Transakce A se nemůže dokončit, dokud transakce B nedokončí, ale transakce B je blokována transakcí A. Tato podmínka se také nazývá cyklická závislost: Transakce A má závislost na transakci B a transakce B zavře kruh tím, že má závislost na transakci A.
Obě transakce v vzájemném zablokování musí čekat navždy, pokud není toto vzájemné zablokování přerušeno externím procesem. Monitor vzájemného zablokování databázového enginu pravidelně kontroluje úlohy, které jsou ve vzájemném zablokování. Pokud monitor zjistí cyklickou závislost, zvolí jeden z úkolů jako oběť a ukončí svou transakci chybou. Tím umožníte druhému úkolu dokončit svou transakci. Aplikace s transakcí ukončenou chybou může opakovat transakci, která se obvykle dokončí po dokončení druhé zablokované transakce.
Systémové zablokování je často zaměňováno s normálním blokováním. Když transakce požádá o zámek prostředku uzamčeného jinou transakcí, čeká, dokud se zámek neuvolní. Ve výchozím nastavení nedojde k vypršení časového limitu transakcí v databázovém stroji, pokud LOCK_TIMEOUT není nastaveno. Žádost o transakci je blokována, není zablokovaná, protože žádající transakce neudělala nic, aby blokovala transakci, která vlastní zámek. Nakonec se vlastní transakce dokončí a uvolní zámek, a pak je žádající transakci udělen zámek a ona pokračuje. Zablokování se řeší téměř okamžitě, zatímco blokování může teoreticky trvale trvat. Zablokování se někdy nazývá smrtelné objetí.
Zablokování může nastat v jakémkoli systému s více vlákny, nejen v systému pro správu relačních databází, a může dojít u jiných prostředků než zámků databázových objektů. Například vlákno ve vícevláknovém operačním systému může získat jeden nebo více prostředků, například bloky paměti. Pokud získaný prostředek aktuálně vlastní jiné vlákno, může první vlákno počkat, až vlastní vlákno uvolní cílový prostředek. Říká se, že čekající vlákno má závislost na vlastnícím vlákně pro daný prostředek. V instanci databázového stroje se mohou relace vzájemně zablokovat při získávání nedatabázových prostředků, jako je paměť nebo vlákna.
Na obrázku má transakce T1 závislost na transakci T2 pro prostředek uzamčení Part tabulky. Podobně má transakce T2 závislost na transakci T1 kvůli prostředku zamčení tabulky Supplier. Vzhledem k tomu, že tyto závislosti tvoří cyklus, mezi transakcemi T1 a T2 je vzájemné zablokování.
Tady je obecnější ilustrace vzájemného zablokování:
Úkol T1 má zámek na zdroji R1 (označený šipkou od R1 do T1) a požádal o zámek prostředku R2 (označený šipkou od T1 do R2).
Úkol T2 má zámek na zdroji R2 (označený šipkou od R2 do T2) a požádal o zámek prostředku R1 (označený šipkou od T2 do R1).
Vzhledem k tomu, že ani jeden úkol nemůže pokračovat, dokud není zdroj dostupný, a dokud úkol nebude pokračovat, nemůže být zdroj uvolněn, existuje stav zablokování.
Note
Databázový stroj automaticky rozpozná cykly zablokování. Zvolí jednu z transakcí jako oběť vzájemného zablokování a ukončí ji chybou, aby přerušila vzájemné zablokování.
Prostředky, které mohou způsobit uvíznutí
Každá uživatelská relace může mít jeden nebo více úkolů, které se provádí ve prospěch relace, přičemž každý úkol může získat nebo čekat na získání zdrojů. Následující typy prostředků můžou způsobit blokování, které by mohlo vést k vzniku deadlocku.
Locks. Čekání na získání zámků u prostředků, jako jsou objekty, stránky, řádky, metadata a aplikace, může způsobit zablokování. Například transakce T1 má sdílený (
S) zámek na řádku r1 a čeká na získání výhradního zámku (X) na r2. Transakce T2 má sdílený zámek (S) na r2 a čeká na získání výhradního zámku (X) na řádku r1. Výsledkem je cyklus uzamčení, ve kterém T1 a T2 vzájemně čekají na uvolnění uzamčených prostředků.Pracovní vlákna. Úkol čekající ve frontě na dostupné pracovní vlákno může způsobit zablokování (deadlock). Pokud úkol ve frontě vlastní prostředky, které blokují všechna pracovní vlákna, dojde k zablokování. Například relace S1 spustí transakci a získá sdílený zámek (
S) na řádku r1 a pak přejde do režimu spánku. Aktivní sessiony spuštěné ve všech dostupných pracovních vláknech se snaží získat exkluzivní zámky (X) na řádku r1. Vzhledem k tomu, že relace S1 nemůže získat pracovní vlákno, nemůže potvrdit transakci a uvolnit zámek na řádku r1. Výsledkem je vzájemné zablokování.Memory. Pokud souběžné požadavky čekají na udělení paměti, které nelze s dostupnou pamětí splnit, může dojít k zablokování. Například dva souběžné dotazy Q1 a Q2 se spouštějí jako uživatelem definované funkce, které získávají 10 MB a 20 MB paměti. Pokud každý dotaz potřebuje 30 MB a celková dostupná paměť je 20 MB, musí otázka Q1 a Q2 čekat na uvolnění paměti, což vede k zablokování.
Paralelní prostředky související se spouštěním dotazů Koordinátoři, producenti nebo vlákna příjemců přidružená k portu výměny se můžou navzájem blokovat, což obvykle způsobuje zablokování, pokud zahrnete alespoň jeden jiný proces, který není součástí paralelního dotazu. Při spuštění paralelního dotazu určuje databázový stroj také stupeň paralelismu a počet požadovaných pracovních vláken na základě aktuální úlohy. Pokud se systémová úloha neočekávaně změní, například když se na serveru začnou spouštět nové dotazy nebo systém vyčerpá pracovní vlákna, může dojít k zablokování.
Několik prostředků MARS (Active Result Sets). Tyto prostředky slouží k řízení prokládání více aktivních požadavků v rámci MARS. Další informace naleznete v tématu Použití více aktivních sad výsledků (MARS) v sql Server Native Client.
Uživatelský zdroj Když vlákno čeká na prostředek, který může být řízen uživatelskou aplikací, je tento prostředek považován za externí nebo uživatelský a zachází se s ním jako se zámkem.
Mutex relace. Úlohy spuštěné v jedné relaci jsou prokládány, což znamená, že v každém okamžiku může být spuštěn pouze jeden úkol v rámci této relace. Před spuštěním úlohy musí mít výhradní přístup k relačnímu mutexu.
Transakční mutex. Všechny úlohy spuštěné v jedné transakci se prokládají, což znamená, že v daném okamžiku může v rámci transakce běžet pouze jeden úkol. Před spuštěním úlohy musí mít výhradní přístup k zámku transakce.
Aby bylo možné úlohu spustit v rámci MARS, musí získat mutex relace. Pokud úloha běží v rámci transakce, musí získat mutex transakce. To zaručuje, že v dané relaci a dané transakci je aktivní pouze jeden úkol najednou. Po získání požadovaných mutexů může úloha spustit. Jakmile se úkol dokončí, nebo pokud se přeruší uprostřed požadavku, nejprve uvolní mutex transakce, následovaný mutex relace, v obráceném pořadí získání. K zablokování ale může dojít u těchto prostředků. V následujícím pseudokódu jsou ve stejné relaci spuštěny dvě úlohy, požadavek uživatele U1 a požadavek uživatele U2.
U1: Rs1=Command1.Execute("insert sometable EXEC usp_someproc"); U2: Rs2=Command2.Execute("select colA from sometable");Uložená procedura spuštěná z požadavku uživatele U1 získala mutex relace. Pokud spuštění uložené procedury trvá dlouho, předpokládá databázový stroj, že uložená procedura čeká na vstup od uživatele. Požadavek uživatele U2 čeká na mutex relace, zatímco uživatel čeká na sadu výsledků z U2 a U1 čeká na uživatelský prostředek. Toto je stav vzájemného zablokování logicky znázorněný takto:
K zablokování může dojít také v případě, že je tabulka rozdělena a parametr LOCK_ESCALATION je nastaven na ALTER TABLE. Pokud je LOCK_ESCALATION nastaveno na AUTO, konkurence se zvýší tím, že databázovému systému umožní uzamknout oddíly tabulky na úrovni HoBT místo na úrovni tabulky. Pokud však samostatné transakce uchovávají zámky oddílů v tabulce a chtějí zámek někde na druhém oddílu transakcí, způsobí to zablokování. Tento typ zablokování lze vyhnout nastavením LOCK_ESCALATION na TABLE. Tímto nastavením se však snižuje souběžnost, protože velké aktualizace oddílů musí čekat na uzamčení tabulky.
Detekce vzájemného zablokování
Všechny prostředky uvedené v části Prostředky, které se mohou vzájemně zablokovat, se účastní schématu detekce vzájemného zablokování databázového stroje. Detekci zablokování provádí vlákno monitorování zámků, které pravidelně spouští vyhledávání prostřednictvím všech úloh v instanci Databázového systému. Následující body popisují proces hledání:
Výchozí interval je 5 sekund.
Pokud vlákno monitorování zámku najde zablokování, interval detekce vzájemného zablokování klesne od 5 sekund do až 100 milisekund v závislosti na frekvenci zablokování.
Pokud vlákno monitorování zámku přestane vyhledávat zablokování, databázový stroj zvýší intervaly mezi hledáním na 5 sekund.
Pokud se zjistí zablokování, předpokládá se, že nová vlákna, která musí čekat na zámek, stávají součástí cyklu zablokování. Prvních několik čekání na zámek po zjištění zablokování okamžitě spustí hledání zablokování, aniž by čekalo na další interval detekce zablokování. Pokud je například aktuální interval 5 sekund a právě bylo zjištěno zablokování, další čekání na uzamčení okamžitě spustí detektor vzájemného zablokování. Pokud je toto uzamčení součástí zablokování, je detekováno hned, a ne během dalšího hledání zablokování.
Databázový stroj obvykle provádí periodické zjišťování vzájemného zablokování. Vzhledem k tomu, že počet zjištěných zablokování v systému je obvykle malý, pomáhá pravidelná detekce zablokování snížit režii detekce zablokování v systému.
Když monitor zámku zahájí vyhledávání určitého vlákna, identifikuje prostředek, na kterém vlákno čeká. Monitor zámků pak nalezne vlastníky konkrétního prostředku a rekurzivně pokračuje ve vyhledávání zablokování pro tato vlákna, dokud nenajde cyklus. Cyklus identifikovaný tímto způsobem tvoří zablokování.
Po zjištění deadlocku databázový stroj ukončí deadlock výběrem jednoho z vláken jako oběti deadlocku. Databázový engine ukončí aktuální dávku, která je spuštěna pro konkrétní vlákno, zruší transakci, jež je obětí zámku, a vrátí chybu 1205 do aplikace. Vrácení transakce pro oběť zablokování uvolní všechny zámky, které transakce drží. To umožňuje, aby transakce ostatních vláken mohly být odblokovány a pokračovat. Chyba 1205 (oběť uváznutí) zaznamenává informace o typu prostředků zapojených do uváznutí.
Ve výchozím nastavení databázový stroj zvolí jako oběť zablokování transakci, jejíž vrácení zpět je nejméně nákladné. Případně může uživatel pomocí příkazu SET DEADLOCK_PRIORITY určit prioritu relací v situaci zablokování.
DEADLOCK_PRIORITY lze nastavit na LOWhodnotu , NORMALnebo HIGHnebo na libovolnou celočíselnou hodnotu v rozsahu od -10 do 10. V některých případech se databázový stroj může rozhodnout změnit prioritu vzájemného zablokování na krátkou dobu, aby se dosáhlo lepší souběžnosti.
Priorita vzájemného zablokování se ve výchozím nastavení nastaví na NORMAL nebo 0. Pokud dvě relace mají různé priority vzájemného zablokování, transakce v relaci s nižší prioritou je zvolena jako oběť vzájemného zablokování. Pokud obě relace mají stejnou prioritu vzájemného zablokování, je zvolena transakce, která je nejméně náročná na vrácení zpět. Pokud relace zapojené do cyklu vzájemného zablokování mají stejnou prioritu a stejné náklady, oběť je vybrána náhodně. Úkol, který se vrací zpět, nejde vybrat jako oběť zablokování.
Při práci s modulem CLR (Common Language Runtime) monitor zablokování automaticky detekuje zablokování u synchronizačních prostředků (monitory, zámek pro čtení a zápis a spojení vláken) přístupné uvnitř spravovaných procedur. Vzájemné zablokování je však vyřešeno vyvoláním výjimky v postupu, který byl vybrán jako oběť vzájemného zablokování. Je důležité si uvědomit, že výjimka automaticky nevyvolá prostředky aktuálně vlastněné obětí; prostředky musí být explicitně vydány. V souladu s chováním výjimek lze výjimku použitou k identifikaci oběti vzájemného zablokování zachytit a ignorovat.
Nástroje poskytující informace o vzájemném zablokování
Databázový stroj poskytuje nástroje pro monitorování ve formě rozšířené události xml_deadlock_report, dvou trasovacích příznaků a události grafu vzájemného zablokování v SQL Profileru.
Rozšířená xml_deadlock_report událost je doporučenou metodou pro zachycení informací o vzájemném zablokování.
Rozšířená událost deadlock
V SQL Serveru 2012 (11.x) a novějších verzích xml_deadlock_report by se rozšířená událost měla použít místo třídy událostí grafu zablokování v SQL Trace nebo SQL Profiler.
Relace událostí system_health zaznamenává xml_deadlock_report události ve výchozím nastavení. Tyto události obsahují graf zablokování.
system_health Vzhledem k tomu, že je relace ve výchozím nastavení povolená, nemusíte konfigurovat samostatnou relaci událostí pro zachycení informací o vzájemném zablokování.
Zachycený graf vzájemného zablokování má obvykle tři různé uzly:
-
victim-list. Identifikátor procesu oběti deadlocku. -
process-list. Informace o všech procesech, které se na zablokování podílejí. -
resource-list. Informace o prostředcích, které jsou součástí zablokování.
Cílová data event_file relace můžete zobrazit v sadě Management Studio system_health. Pokud dojde k nějakým xml_deadlock_report událostem, Management Studio zobrazí grafické znázornění úloh a prostředků, které jsou součástí zablokování, jak je vidět v následujícím příkladu:
Následující dotaz může prohlížet všechny situace uvíznutí zachycené cílem ring_buffer relace system_health:
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;
Tady je soubor výsledků.
Následující příklad ukazuje příklad výstupu event_data ze sloupce:
<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>
Příznak trasování 1204 a příznak trasování 1222
Pokud dojde k deadlocku a trasovací stopa 1204 nebo trasovací stopa 1222 je povolena, podrobnosti o zablokování se hlásí v chybovém protokolu SQL Serveru. Příznak trasování 1204 hlásí informace o vzájemném zablokování formátované jednotlivými uzly, které jsou součástí zablokování. Příznak trasování 1222 formátuje informace o vzájemném zablokování, nejprve podle procesů a potom podle prostředků. Je možné povolit oba trasovací příznaky, aby bylo možné získat dvě reprezentace stejné události zablokování.
Important
Nepoužívejte příznaky trasování 1204 a 1222 v systémech s vysokou zátěží, u kterých dochází k zablokování. Používání těchto příznaků trasování může způsobit výkonové problémy. Místo toho použijte Deadlock rozšířenou událost k zachycení potřebných informací.
Kromě definování vlastností příznaků trasování 1204 a 1222 ukazuje následující tabulka také podobnosti a rozdíly.
| Property | Příznak trasování 1204 a příznak trasování 1222 | Pouze příznak trasování 1204 | Pouze příznak trasování 1222 |
|---|---|---|---|
| Výstupní formát | Výstup se zaznamenává v protokolu chyb SQL Serveru. | Je zaměřeno na uzly zapojené do vzájemného zablokování. Každý uzel má vyhrazenou část a poslední část popisuje oběť zablokování. | Vrátí informace ve formátu podobném formátu XML, který neodpovídá schématu definice schématu XML (XSD). Formát má tři hlavní části. První sekce deklaruje oběť vzájemného zablokování. Druhá část popisuje jednotlivé procesy spojené se vzájemným zablokováním. Třetí část popisuje prostředky, které odpovídají uzlům v příznaku sledování 1204. |
| Identifikace atributů |
SPID:<x> ECID:<x>. Identifikuje vlákno ID sezení při paralelních procesech. Položka SPID:<x> ECID:0, kde <x> je nahrazena hodnotou SPID, představuje hlavní vlákno. Položka SPID:<x> ECID:<y>, kde <x> je nahrazena hodnotou SPID a <y> je větší než 0, představuje kontext spuštění pro stejné SPID.BatchID (sbid pro příznak trasování 1222). Identifikuje dávku, ze které se vyžaduje spuštění kódu nebo drží zámek. Pokud je zakázáno více aktivních sad výsledků (MARS), BatchID má hodnotu 0. Pokud je povolená funkce MARS, hodnota aktivních dávek je 1 až n. Pokud v relaci nejsou žádné aktivní dávky, BatchID je 0.Mode Určuje typ zámku pro konkrétní prostředek, který je požadován, udělen nebo na který vlákno čeká. Režim může být záměr sdílený (IS), sdílený (S), aktualizace (U), záměr výhradní (IX), sdílený s záměrem výhradním (SIX) a výhradní (X).Line # (line pro příznak trasování 1222). Zobrazí číslo řádku v aktuální dávce příkazů, které se spouštěly, když došlo k zablokování.Input Buf (inputbuf pro příznak trasování 1222). Zobrazí seznam všech příkazů v aktuální dávce. |
Node Představuje vstupní číslo v řetězci vzájemného zablokování.Lists Vlastník zámku může být součástí těchto seznamů:Grant List Vytvoří výčet aktuálních vlastníků prostředku.Convert List Vytvoří výčet aktuálních vlastníků, kteří se pokoušejí převést zámky na vyšší úroveň.Wait List Vytvoří výčet aktuálních nových žádostí o uzamčení prostředku.Statement Type Popisuje typ příkazu (SELECT, INSERT, UPDATE, nebo DELETE), u kterého mají vlákna oprávnění.Victim Resource Owner Určuje zúčastněné vlákno, které databázový stroj zvolí jako oběť k přerušení cyklu vzájemného zablokování. Vybrané vlákno a všechny jeho kontexty spuštění jsou ukončeny.Next Branch Představuje dva nebo více kontextů provádění ze stejného SPID, které jsou zapojeny do cyklu deadlocku. |
deadlock victim Představuje adresu fyzické paměti úkolu (viz sys.dm_os_tasks), která byla vybrána jako oběť zablokování. Hodnota může být nula v případě nevyřešeného zablokování.executionstack Představuje zásobník volání Transact-SQL, který se spouští v době, kdy dojde k uváznutí.priority Představuje prioritu zablokování.logused Prostor pro protokoly používaný úlohou.owner id ID transakce, která má kontrolu nad požadavkem.status Stav úkolu. Další informace najdete v tématu sys.dm_os_tasks.waitresource Zdroj, který úkol potřebuje.waittime Čas v milisekundách čekání na prostředekschedulerid Plánovač přidružený k této úloze. Viz sys.dm_os_schedulers.hostname Název pracovní stanice.isolationlevel Aktuální úroveň izolace transakcí.Xactid ID transakce, která má kontrolu nad požadavkem.currentdb ID databáze.lastbatchstarted Čas, kdy klientský proces naposledy spustil dávkové zpracování.lastbatchcompleted Naposledy čas, kdy proces klienta dokončil dávkové provádění.clientoption1 a clientoption2 Nastavte možnosti pro tuto relaci. Tyto hodnoty jsou bitové masky představující možnosti obvykle řízené SET příkazy jako SET NOCOUNT a SET XACTABORT. Další informace najdete v tématu @@OPTIONS.associatedObjectId Představuje ID HoBT (halda nebo B-tree — datová struktura typu strom). |
| Atributy zdroje |
RID identifikuje jeden řádek v tabulce, na které je zámek uložen nebo požadován. Identifikátor RID je reprezentován jako RID: db_id:file_id:page_no:row_no. Například: RID: 6:1:20789:0.OBJECT identifikuje tabulku, na které je zámek uložen nebo požadován.
OBJECT je reprezentován jako OBJECT: db_id:object_id. Například: TAB: 6:2009058193.KEY Identifikuje rozsah klíčů v indexu, na kterém je zámek držen nebo žádán. KLÍČ je reprezentován jako KLÍČ: db_id:hobt_id (hodnota hash indexového klíče). Například: KEY: 6:72057594057457664 (350007a4d329).PAG Identifikuje prostředek stránky, na kterém je zámek uložen nebo požadován.
PAG je reprezentován jako PAG: db_id:file_id:page_no. Například: PAG: 6:1:20789.EXT Identifikuje strukturu rozsahu.
EXT je reprezentován jako EXT: db_id:file_id:extent_no. Například: EXT: 6:1:9.DB Identifikuje zámek databáze.
DB je reprezentován jedním z následujících způsobů:DB: db_idDB: db_id[BULK-OP-DB], který identifikuje zámek databáze pořízený zálohováním databáze.DB: db_id[BULK-OP-LOG], který identifikuje zámek pořízený zálohou protokolu.APP Identifikuje zámek aplikace.
APP je reprezentován jako APP: lock_resource. Například: APP: Formf370f478.METADATA Představuje zdroje metadat zapojené do vzájemného zablokování. Protože METADATA má mnoho dílčích zdrojů, vrácená hodnota závisí na dílčím zdroji, který má zablokování. Například METADATA.USER_TYPE vrátí user_type_id = *integer_value*. Další informace o METADATA prostředcích a dílčích zdrojích najdete v sys.dm_tran_locks.HOBT Představuje haldu nebo strom B zapojený do vzájemného zablokování. |
Neexistuje žádná výhradní značka pro tento příznak trasování. | Neexistuje žádná výhradní značka pro tento příznak trasování. |
Příklad příznaku trasování 1204
Následující příklad ukazuje výstup při zapnutém trasovacím příznaku 1204. V tomto případě je tabulka v uzlu 1 haldou bez indexů a tabulka v Node 2 je haldou s neclusterovaným indexem. Klíč indexu v uzlu 2 se aktualizuje, když dojde k zablokování.
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)
Příklad trasovacího příznaku 1222
Následující příklad ukazuje výstup při zapnutí příznaku trasování 1222. V tomto případě je jedna tabulka haldou bez indexů a druhou tabulkou je halda s neclusterovaným indexem. Ve druhé tabulce se klíč indexu aktualizuje, když dojde k zablokování.
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
Událost grafu zablokování profileru
SQL Profiler má událost, která představuje grafické znázornění úkolů a prostředků zapojených do zablokování. Výstup v SQL Profileru, když je událost grafu zácpy zapnutá, ukazuje následující příklad.
Funkce SQL Profileru a trasování SQL jsou zastaralé a nahrazené rozšířenými událostmi. Rozšířené události mají menší režii na výkon a jsou více konfigurovatelné než trasování SQL. Místo trasování zablokování v SQL Profileru zvažte použití události zablokování v rámci rozšířených událostí.
Další informace o události deadlocku naleznete v tématu Lock:Deadlock Event Class. Další informace o grafech vzájemného zablokování sql Profileru najdete v tématu Ukládání grafů vzájemného zablokování (SQL Server Profiler).
Rozšířené události poskytují ekvivalenty tříd trasování událostí SQL. Další informace naleznete v tématu Zobrazení rozšířených událostí ekvivalentů ke třídám událostí trasování SQL. Doporučuje se používat rozšířené události místo trasování SQL.
Zpracování vzájemných zablokování
Když instance databázového enginu zvolí transakci jako oběť deadlocku, ukončí aktuální dávku, transakci vrátí zpět a vrátí chybu 1205 do aplikace. Vrácená zpráva je strukturovaná takto:
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.
Vzhledem k tomu, že každá aplikace odesílající dotazy Transact-SQL může být vybrána jako oběť zablokování, aplikace by měly mít obslužnou rutinu, která dokáže zpracovat chybu 1205. Pokud aplikace chybu nezachytí, může pokračovat, aniž by si uvědomila, že její transakce byla vrácena zpět.
Implementace obslužné rutiny chyby, která zachytává chybu 1205, umožňuje aplikaci zpracovat zablokování a provést nápravnou akci (například automaticky znovu odeslat dotaz, který byl součástí zablokování).
Aplikace by se měla před opětovným odesláním dotazu krátce pozastavit. To dává druhé transakci zapojené do vzájemného zablokování šanci dokončit a uvolnit zámky. Randomizace délky trvání pozastavení minimalizuje pravděpodobnost opětovného uvíznutí, když znovu podaný dotaz požaduje jeho zámky. Obslužná rutina chyby může být například kódována tak, aby se pozastavila na náhodnou dobu mezi 1 a třemi sekundami.
Zpracování s TRY...CATCH
Můžete použít funkci TRY... CATCH pro zpracování zablokování. Chyba 1205 může být zachycena blokem CATCH.
Další informace naleznete v tématu Zpracování zablokování.
Minimalizace zablokování
Přestože se vzájemnému zablokování nejde zcela vyhnout, dodržováním určitých konvencí psaní kódu je možné pravděpodobnost vzniku vzájemného zablokování minimalizovat. Minimalizací výskytu vzájemných zablokování se může zvýšit propustnost transakcí a snížit režii systému, a to z následujících důvodů:
- Méně transakcí se vrací zpět (čímž se zruší veškerá jimi provedená práce).
- Aplikace znovu odesílají méně vrácených transakcí kvůli vzájemnému zablokování.
Pro minimalizaci zablokování:
- Přistupujte k objektům ve stejném pořadí.
- Vyhněte se interakci uživatelů v transakcích.
- Udržujte transakce krátké a v jedné dávce.
- Vyhněte se vyšším úrovním izolace, jako jsou
REPEATABLE READaSERIALIZABLE, pokud nejsou potřeba. - Použijte úroveň izolace založenou na verzích řádků.
-
READ_COMMITTED_SNAPSHOTPovolte možnost databáze používat verzování řádků pro transakce pomocíREAD COMMITTEDúrovně izolace. - Použijte transakce izolace snímků.
-
- Používejte vázaná připojení.
Přístup k objektům ve stejném pořadí
Pokud všechny souběžné transakce přistupují k objektům ve stejném pořadí, zablokování je méně pravděpodobné. Pokud například dvě souběžné transakce získávají zámek v Supplier tabulce a pak v Part tabulce, jedna transakce je blokována v Supplier tabulce, dokud se nedokončí druhá transakce. Jakmile se první transakce potvrdí nebo vrátí zpět, druhá transakce pokračuje a zablokování nenastane. Použití uložených procedur pro všechny úpravy dat může standardizovat pořadí přístupu k objektům.
Vyhněte se interakci uživatelů v transakcích
Vyhněte se transakcím, které zahrnují interakci uživatele, protože rychlost dávek spuštěných bez zásahu uživatele je mnohem rychlejší než rychlost, s jakou musí uživatel ručně reagovat na dotazy, například odpovědět na výzvu k zadání parametru požadovaného aplikací. Tím se sníží propustnost systému, protože všechny zámky držené transakcí se uvolní až po potvrzení nebo vrácení transakce. I když nedojde k zablokování, ostatní transakce, které přistupují ke stejným prostředkům, se zablokují při čekání na dokončení transakce.
Udržujte transakce krátké a v jedné dávce
Ke vzájemnému zablokování obvykle dochází při souběžném provádění několika dlouhotrvajících transakcí ve stejné databázi. Čím déle trvá transakce, tím déle se uchovávají výhradní zámky nebo zámky na aktualizaci, což blokuje další činnost a vede k možným zablokováním.
Udržování transakcí v jedné dávce minimalizuje počet síťových přenosů během transakce, což snižuje možné zpoždění při dokončování transakce kvůli zpracování na straně klienta.
Vyhněte se vyšším úrovním izolace
Určete, zda transakce může běžet na nižší úrovni izolace. Použití READ COMMITTED umožňuje transakci číst data dříve přečtená (ale neupravována) jinou transakcí bez čekání na dokončení transakce.
READ COMMITTED uchovává sdílené zámky po kratší dobu než vyšší úroveň izolace, například SERIALIZABLE. Tím se omezí kolize zámků.
Použití úrovně izolace založené na verzování řádků
Pokud je nastavena možnost databáze READ_COMMITTED_SNAPSHOTON, transakce spuštěná na úrovni izolace READ COMMITTED, používá správu verzí řádků místo aby používala sdílené zámky během operací čtení.
Návod
Microsoft doporučuje úroveň izolace na základě READ COMMITTED správy verzí řádků pro všechny aplikace, pokud aplikace nepoužívá k blokování chování na úrovni izolace založené na READ COMMITTED zámku.
Izolace snímků používá také verzování řádků, které při operacích čtení nepoužívá sdílené zámky. Před tím, než může transakce běžet pod izolací snímku, musí být nastavena volba databáze ALLOW_SNAPSHOT_ISOLATIONON.
Úrovně izolace založené na správě verzí řádků můžete použít k minimalizaci zablokování, ke kterým může dojít mezi operacemi čtení a zápisu.
Použijte vázaná připojení
Pomocí vázaná připojení můžou dvě nebo více připojení otevřených stejnou aplikací vzájemně spolupracovat. Všechny zámky získané sekundárními připojeními se uchovávají, jako by byly získány primárním připojením a naopak. Proto se navzájem nezablokují.
Způsobit zablokování
Možná budete muset způsobit zablokování pro výuku nebo demonstrační účely.
Následující příklad funguje v AdventureWorksLT2019 ukázkové databázi s výchozím schématem a daty, pokud je povolená READ_COMMITTED_SNAPSHOT. Pokud si chcete tuto ukázku stáhnout, navštivte ukázkové databáze AdventureWorks.
Příklad, který způsobí deadlock při povoleném optimalizovaném uzamčení, najdete v tématu Optimalizované uzamčení a deadlocky.
Pokud chcete způsobit zablokování, musíte k databázi AdventureWorksLT2019 připojit dvě relace. Na tyto relace odkazujeme jako na relaci A a relaci B. Tyto dvě relace můžete vytvořit vytvořením dvou oken dotazů v aplikaci SQL Server Management Studio (SSMS).
V seanci A spusťte následující skript. Tento kód zahájí explicitní transakci a spustí příkaz, který aktualizuje SalesLT.Product tabulku. Za tímto účelem transakce získá zámek aktualizace (U) na vyhovujících řádcích v tabulce SalesLT.Product, které jsou následně převedeny na výhradní (X) zámky. Transakci ponecháme otevřenou.
BEGIN TRANSACTION;
UPDATE SalesLT.Product
SET SellEndDate = SellEndDate + 1
WHERE Color = 'Red';
Teď v relaci B spusťte následující dávku. Tento kód explicitně nezačne transakci. Místo toho funguje v režimu automatické transakce. Tento příkaz aktualizuje SalesLT.ProductDescription tabulku. Aktualizace převezme zámek pro aktualizaci na U vhodných řádcích v SalesLT.ProductDescription tabulce. Dotaz se spojí s jinými tabulkami, včetně SalesLT.Product tabulky.
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';
K dokončení této aktualizace potřebuje relace B sdílené zámky (S) na řádcích v tabulce SalesLT.Product, včetně řádků, které jsou uzamčeny relací A. Relace B je zablokovaná SalesLT.Product.
Vraťte se do relace A. Spusťte následující UPDATE příkaz. Tento příkaz se provádí jako součást dříve otevřené transakce.
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';
Druhý příkaz aktualizace v Relace A je blokován Relace B na SalesLT.ProductDescription.
Relace A a Relace B se teď vzájemně blokují. Žádná transakce nemůže pokračovat, protože každý potřebuje prostředek, který je uzamčen jiným.
Po několika sekundách monitor zablokování zjistí, že transakce v relaci Session A a relaci Session B se vzájemně blokují a že ani jedna nemůže pokračovat. Uvidíte, že dojde k vzájemnému zablokování, přičemž se relace A stane obětí. Sezení B úspěšně dokončeno. V okně dotazu Session A se zobrazí chybová zpráva s textem podobným následujícímu příkladu:
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.
Pokud se zablokování nevyvolá, ověřte, že READ_COMMITTED_SNAPSHOT je ve vaší ukázkové databázi povolené. Zablokování může nastat v jakékoli konfiguraci databáze, ale tento příklad vyžaduje povolení READ_COMMITTED_SNAPSHOT .
Podrobnosti o vzájemném zablokování můžete zobrazit v ring_buffer cíli system_health relace událostí, která je ve výchozím nastavení povolená a aktivní v SQL Serveru a ve spravované instanci Azure SQL. Představte si následující dotaz:
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;
Xml ve sloupci uvnitř Deadlock_XML aplikace SSMS můžete zobrazit tak, že vyberete buňku, která se zobrazí jako hypertextový odkaz. Uložte tento výstup jako .xdl soubor, zavřete .xdl soubor, a pak jej znovu otevřete v aplikaci SSMS pro vizuální graf zablokování. Graf vzájemného zablokování by měl vypadat podobně jako na následujícím obrázku.
Optimalizované uzamykání a zablokování
S optimalizovaným uzamykáním nejsou zámky stránek a řádků drženy až do konce transakce. Uvolněny ihned poté, co je řádek aktualizován. Pokud je navíc READ_COMMITTED_SNAPSHOT povoleno, aktualizační zámky (U) se nepoužívají. V důsledku toho se sníží pravděpodobnost zablokování.
Předchozí příklad nezpůsobí zablokování, když je povoleno optimalizované uzamčení, protože se spoléhá na zámky aktualizace (U).
Následující příklad lze použít k zablokování databáze, která má optimalizované uzamčení povolenou.
Nejprve vytvořte ukázkovou tabulku a přidejte data.
CREATE TABLE t2
(
a INT PRIMARY KEY NOT NULL,
b INT NULL
);
INSERT INTO t2
VALUES (1, 10),
(2, 20),
(3, 30);
Následující dávky T-SQL, spuštěné postupně ve dvou samostatných sezeních, vytvoří deadlock.
V relaci 1:
BEGIN TRANSACTION xactA;
UPDATE t2
SET b = b + 10
WHERE a = 1;
Ve sezení 2:
BEGIN TRANSACTION xactB;
UPDATE t2
SET b = b + 10
WHERE a = 2;
V relaci 1:
UPDATE t2
SET b = b + 100
WHERE a = 2;
Ve sezení 2:
UPDATE t2
SET b = b + 20
WHERE a = 1;
V tomto případě každá relace obsahuje výhradní zámek (X) u vlastního prostředku ID transakce (TID) a čeká na sdílený zámek (S) na druhém TID, což vede k zablokování.
Následující zkrácená zpráva o patové situaci obsahuje prvky a atributy určené pro optimalizaci uzamykání. Pod každým prostředkem v sestavě <resource-list>vzájemného zablokování každý <xactlock> prvek hlásí podkladové prostředky a informace o zámku TID každého člena zablokování.
<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>
Související obsah
- přehled rozšířených událostí
- sys.dm_tran_locks (Transact-SQL)
- Třída událostí grafu vzájemného zablokování
- Zablokování s opakovatelnou úrovní izolace pro čtení
- Lock:Deadlock Chain – třída událostí
- Lock:Deadlock – třída události
- SET DEADLOCK_PRIORITY (Transact-SQL)
- Analýza a prevence zablokování ve službě Azure SQL Database a SQL Database v Fabric
- Otevření, zobrazení a tisk souboru zablokování v aplikaci SQL Server Management Studio (SSMS)