Przejdź do treści
Powrót do Centrum Pomocy
SQL Server
Poradniki

SQL Server Deadlock — jak zdiagnozować i naprawić zakleszczenia w 2026 roku

Deadlock (nazywany też deadly embrace — śmiertelnym uściskiem) to szczególny przypadek blokowania, w którym żadna z transakcji nie może postąpić naprzód. W prze

11 min czytania·Zaktualizowano dzisiaj
Faktura VAT 23% + KSeFDostawa 1-3 min e-mailemGwarancja działania klucza5,0 / 5,0(KluczeSoft)

Deadlock (zakleszczenie) w SQL Server to sytuacja, w której dwie lub więcej transakcji wzajemnie się blokują — każda czeka na zasób zablokowany przez drugą, tworząc cykliczną zależność. SQL Server automatycznie wykrywa deadlocki (monitor sprawdza co 5 sekund, a przy ich wykryciu nawet co 100 ms) i rozwiązuje je, wybierając jedną z transakcji jako ofiarę (victim) — kończy ją błędem 1205, co pozwala drugiej transakcji kontynuować pracę.

W skrócie

  • Deadlock to nie blokowanie (blocking) — blokowanie mija, gdy właściciel zwolni zasób; deadlock trwałby w nieskończoność, gdyby nie interwencja monitora
  • SQL Server automatycznie kończy deadlock błędem 1205 — aplikacja musi go obsłużyć i ponowić transakcję
  • Główne narzędzie diagnostyczne w 2026: system_health Extended Event (domyślnie włączony) — przechowuje pełne raporty deadlocków w XML
  • W SQL Server 2022/2025 wprowadzono Optimized Locking — zmniejsza ryzyko deadlocków przez wcześniejsze zwalnianie blokad wierszy i stron
  • Kluczowa profilaktyka: READ_COMMITTED_SNAPSHOT ON, krótkie transakcje, dostęp do obiektów w tej samej kolejności

Czym dokładnie jest deadlock w SQL Server

Deadlock (nazywany też deadly embrace — śmiertelnym uściskiem) to szczególny przypadek blokowania, w którym żadna z transakcji nie może postąpić naprzód. W przeciwieństwie do zwykłego blokowania (gdzie transakcja A czeka na B, ale B nie czeka na A — więc B w końcu się zakończy i zwolni zasób), w deadlocku A czeka na B i jednocześnie B czeka na A.

Prosty mechanizm — przykład

  1. Transakcja A zakłada blokadę współdzieloną (S) na wierszu 1.
  2. Transakcja B zakłada blokadę współdzieloną (S) na wierszu 2.
  3. Transakcja A żąda blokady wyłącznej (X) na wierszu 2 — czeka na zwolnienie blokady przez B.
  4. Transakcja B żąda blokady wyłącznej (X) na wierszu 1 — czeka na zwolnienie blokady przez A.

W tym momencie obie transakcje czekają na siebie nawzajem. Bez interwencji zewnętrznego mechanizmu czekałyby w nieskończoność.

Rodzaje zasobów, które mogą powodować deadlocki

Deadlocki w SQL Server nie ograniczają się tylko do blokad na danych. Monitor deadlocków sprawdza następujące typy zasobów:

Typ zasobuOpisPrzykład
LocksBlokady na obiektach, stronach, wierszach, metadanychNajczęstszy typ — rywalizacja o te same dane
Worker threadsWątki roboczeSesja trzymająca blokadę nie może pobrać wątku, by zwolnić blokadę
MemoryPrzydziały pamięci dla zapytańDwa zapytania czekające na siebie przy ograniczonej pamięci
Parallel query resourcesZasoby zapytań równoległychWątki koordynatora/producenta/konsumenta blokujące się wzajemnie
MARS resourcesKontrola przeplotu zapytań w MARSDwa żądania w tej samej sesji czekające na siebie
Session/Transaction mutexWyłączność sesji i transakcjiProcedura składowana blokuje mutex sesji, a drugie żądanie czeka

Jak zdiagnozować deadlock — narzędzia w 2026 roku

1. system_health Extended Event (rekomendowane) ⭐

Od SQL Server 2012 domyślnie uruchomiona jest sesja zdarzeń rozszerzonych system_health, która automatycznie przechwytuje zdarzenia xml_deadlock_report. To podstawowe i zalecane narzędzie diagnostyczne — nie wymaga żadnej konfiguracji.

Raport deadlocka w XML zawiera trzy główne węzły:

  • victim-list — identyfikator procesu wybranego na ofiarę
  • process-list — szczegóły wszystkich procesów: SPID, zapytanie (inputbuf), stos wywołań (executionStack), czas oczekiwania, poziom izolacji, nazwa hosta, login
  • resource-list — zasoby biorące udział w deadlocku: KEY, RID, PAGE, OBJECT z identyfikatorami bazy, obiektu, indeksu

Jak odczytać raport — zapytanie T-SQL:

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;

W SSMS kliknij komórkę z danymi XML — otworzy się graficzny wykres deadlocka (procesy, zasoby, strzałki wskazujące zależności). Możesz też zapisać XML jako plik .xdl i otworzyć go ponownie w SSMS, by uzyskać wizualizację.

2. Trace flag 1204 i 1222 (legacy — unikać na produkcji)

Trace flag 1204 i 1222 zapisują szczegóły deadlocków w SQL Server error log. TF 1204 formatuje dane węzłami, TF 1222 — najpierw procesami, potem zasobami (w formacie XML-podobnym). Można włączyć oba jednocześnie.

Uwaga: Microsoft odradza używanie trace flag 1204/1222 na obciążonych systemach produkcyjnych — mogą powodować problemy wydajnościowe. Zawsze preferuj Extended Events.

3. SQL Profiler — Deadlock Graph (przestarzałe)

SQL Profiler i SQL Trace zostały oficjalnie wycofane (deprecated). Zastąp je Extended Events, które mają mniejszy narzut wydajnościowy i są bardziej konfigurowalne.

Porównanie narzędzi diagnostycznych

NarzędzieZalecane w 2026?Narzut wydajnościowyDomyślnie włączoneGraficzna wizualizacja
system_health XEvent✅ Tak — podstawoweMinimalny✅ Tak✅ Tak (przez SSMS)
TF 1204❌ LegacyZnaczący przy dużym obciążeniu❌ Nie❌ Nie
TF 1222❌ LegacyZnaczący przy dużym obciążeniu❌ Nie❌ Nie
SQL Profiler❌ PrzestarzałeWysoki❌ Nie✅ Tak (wykres)

Jak naprawić i zapobiegać deadlockom

Obsługa błędu 1205 w aplikacji

Każda aplikacja komunikująca się z SQL Server musi mieć handler błędu 1205. Bez niego aplikacja będzie kontynuować pracę, nieświadoma, że jej transakcja została wycofana.

Wzorzec obsługi w T-SQL z użyciem TRY...CATCH:

DECLARE @retry INT = 0;
WHILE @retry < 3
BEGIN
    BEGIN TRY
        BEGIN TRANSACTION;
        -- operacje na danych
        COMMIT;
        BREAK;
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() = 1205
        BEGIN
            ROLLBACK;
            SET @retry = @retry + 1;
            WAITFOR DELAY '00:00:01'; -- losowe opóźnienie 1-3 s
        END;
        ELSE THROW;
    END CATCH;
END;

Kluczowe: losowe opóźnienie przed ponowieniem (1–3 sekundy) zmniejsza prawdopodobieństwo, że deadlock wystąpi ponownie — daje drugiej transakcji czas na zakończenie.

8 sprawdzonych technik zapobiegania deadlockom

1. Dostęp do obiektów w tej samej kolejności

Jeśli wszystkie transakcje pobierają blokady na tabelach A, potem B, potem C — zawsze w tej samej kolejności — cykl zależności nie powstanie. Używanie procedur składowanych do wszystkich modyfikacji danych pomaga ustandaryzować tę kolejność.

2. Krótkie transakcje, jeden batch

Im dłużej trwa transakcja, tym dłużej utrzymywane są blokady wyłączne (X) i aktualizacji (U). Wykonuj całą transakcję w jednym batchu — unikaj round-tripów sieciowych wewnątrz transakcji.

3. Unikaj interakcji z użytkownikiem wewnątrz transakcji

Nigdy nie czekaj na input użytkownika, gdy transakcja jest otwarta. Blokady są zwalniane dopiero po COMMIT lub ROLLBACK — w tym czasie inne transakcje stoją w kolejce.

4. READ_COMMITTED_SNAPSHOT ON (RCSI) ⭐

Najważniejsza rekomendacja Microsoftu dla wszystkich aplikacji:

ALTER DATABASE TwojaBaza SET READ_COMMITTED_SNAPSHOT ON;

Po włączeniu tej opcji transakcje w izolacji READ COMMITTED używają wersjonowania wierszy zamiast blokad współdzielonych podczas odczytów. Oznacza to, że SELECT nie blokuje UPDATE i odwrotnie — eliminuje to najczęstszą przyczynę deadlocków między odczytem a zapisem.

5. Snapshot Isolation

Krok dalej niż RCSI — wymaga ustawienia ALLOW_SNAPSHOT_ISOLATION ON i jawnego użycia SET TRANSACTION ISOLATION LEVEL SNAPSHOT. Zapewnia spójny widok danych na początek transakcji bez żadnych blokad.

6. Unikaj wyższych poziomów izolacji

REPEATABLE READ i SERIALIZABLE utrzymują blokady współdzielone do końca transakcji, drastycznie zwiększając ryzyko deadlocków. Używaj tylko wtedy, gdy jest to absolutnie konieczne.

7. SET DEADLOCK_PRIORITY

Możesz nadać sesji priorytet w sytuacji deadlocka:

SET DEADLOCK_PRIORITY LOW;  -- ta sesja będzie ofiarą
SET DEADLOCK_PRIORITY HIGH; -- ta sesja przetrwa

Skala: od -10 do 10 (domyślnie NORMAL = 0). Sesja z niższym priorytetem zostanie wybrana na ofiarę. Przy równym priorytecie — SQL Server wybiera transakcję najtańszą do wycofania.

8. Optimized Locking (SQL Server 2022/2025)

Nowy mechanizm dostępny w SQL Server 2022 i udoskonalony w wersji 2025. Przy włączonym Optimized Locking blokady wierszy i stron nie są utrzymywane do końca transakcji — są zwalniane natychmiast po zaktualizowaniu wiersza. Dodatkowo, gdy RCSI jest włączone, blokady aktualizacji (U) w ogóle nie są używane. Efekt: znacząco mniej deadlocków, szczególnie przy dużym współbieżnym obciążeniu.


Najczęstsze problemy przy diagnostyce

Nie mogę znaleźć raportu deadlocka w system_health

Ring buffer system_health ma ograniczoną pojemność (domyślnie 4 MB dla każdego targetu). Przy dużej liczbie zdarzeń starsze wpisy są nadpisywane. Rozwiązanie: utwórz dedykowaną sesję Extended Events z targetem event_file:

CREATE EVENT SESSION [DeadlockMonitor] ON SERVER
ADD EVENT sqlserver.xml_deadlock_report
ADD TARGET package0.event_file(SET filename = N'C:\Temp\Deadlocks.xel')
WITH (MAX_MEMORY = 4096 KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
      MAX_DISPATCH_LATENCY = 5 SECONDS);
ALTER EVENT SESSION [DeadlockMonitor] ON SERVER STATE = START;

Deadlocki występują, ale raport nie pokazuje się w system_health

Sprawdź, czy sesja system_health jest uruchomiona:

SELECT name, status_desc FROM sys.dm_xe_sessions WHERE name = 'system_health';

Jeśli status to STOPPED, uruchom ją: ALTER EVENT SESSION system_health ON SERVER STATE = START;

Myli mi się deadlock ze zwykłym blokowaniem (blocking)

Kluczowa różnica: w blokowaniu jest tylko jedna strona czekająca — właściciel zasobu nie czeka na nic od blokowanego. W deadlocku obie strony czekają na siebie. Do diagnostyki blokowania użyj sp_who2, sys.dm_exec_requests z blocking_session_id lub sp_BlitzLock (Brent Ozar).


Częste pytania

Czym różni się deadlock od zwykłego blokowania (blocking)?

W blokowaniu transakcja A czeka na zasób trzymany przez B, ale B nie czeka na A — B w końcu się zakończy i zwolni zasób. Deadlock to cykliczne blokowanie: A czeka na B i B czeka na A. SQL Server rozwiązuje deadlock automatycznie (błąd 1205), natomiast blokowanie może trwać dowolnie długo, dopóki właściciel nie zwolni zasobu.

Czy deadlock w SQL Server oznacza uszkodzenie danych?

Nie. SQL Server wycofuje (ROLLBACK) transakcję-ofiarę, przywracając dane do stanu sprzed jej rozpoczęcia. Żadne dane nie są tracone — aplikacja otrzymuje błąd 1205 i powinna ponowić transakcję. Integralność bazy pozostaje nienaruszona.

Jak sprawdzić, czy w mojej bazie występują deadlocki, bez dostępu do SSMS?

Uruchom zapytanie odczytujące ring buffer system_health (podane wyżej w sekcji diagnostycznej) — działa przez każde narzędzie obsługujące T-SQL: Azure Data Studio, sqlcmd, PowerShell (Invoke-SqlCmd). Alternatywnie, monitoruj licznik PerfMon SQLServer:Locks > Number of Deadlocks/sec.

Czy włączenie READ_COMMITTED_SNAPSHOT ma jakieś wady?

Główna wada to zwiększone zużycie tempdb — SQL Server przechowuje wersje wierszy w tempdb, co przy intensywnych modyfikacjach może obciążyć ten magazyn. Dodatkowo aplikacje polegające na blokującym zachowaniu READ COMMITTED (np. oczekujące na zakończenie innej transakcji przed odczytem) mogą wymagać dostosowania logiki.

Czy Optimized Locking całkowicie eliminuje deadlocki?

Nie. Optimized Locking znacząco redukuje ryzyko deadlocków, ale nie eliminuje ich całkowicie — deadlocki wciąż mogą wystąpić na zasobach takich jak wątki robocze, pamięć czy rywalizacja o Transaction ID (TID). Mechanizm jest jednak najskuteczniejszą dotychczasową optymalizacją Microsoftu w tym obszarze.

Jak sprawdzić, które zapytania najczęściej uczestniczą w deadlockach?

Odczytaj raporty z system_health, wyodrębnij pole inputbuf z każdego procesu i pogrupuj. Możesz też użyć narzędzia sp_BlitzLock z First Responder Kit Brent Ozara, które parsuje system_health i przedstawia zagregowane statystyki — które zapytania, tabele i indeksy pojawiają się najczęściej.

Czy mogę całkowicie pozbyć się deadlocków?

Nie da się ich w 100% wyeliminować w systemie ze współbieżnymi transakcjami — to nieodłączna cecha każdej relacyjnej bazy danych z blokadami. Można jednak zredukować ich częstotliwość do poziomu marginalnego, stosując RCSI, Optimized Locking, krótkie transakcje i ustandaryzowaną kolejność dostępu do obiektów.


Wydajny SQL Server potrzebuje solidnej licencji

Niezależnie od tego, czy stawiasz nowy serwer, migrujesz na SQL Server 2022/2025, czy optymalizujesz istniejącą instancję pod kątem deadlocków — podstawa to legalne i w pełni wspierane środowisko. W KluczeSoft znajdziesz oryginalne licencje Microsoft SQL Server w cenach nawet 70% niższych od sugerowanych — w pełni zgodne z prawem Unii Europejskiej (wyrok TSUE UsedSoft, C-128/11).

Licencje Microsoft SQL Server i Windows Server — sprawdź dostępne edycje


Artykuł opracowano na podstawie oficjalnej dokumentacji Microsoft Learn (Deadlocks Guide, stan na maj 2026), testów w SQL Server 2022/2025 oraz narzędzi społeczności DBATools i First Responder Kit. KluczeSoft jest niezależnym sprzedawcą — nie jest powiązany z Microsoft Corporation.

<!-- IL-V1 -->

Powiązane artykuły

Najczęściej zadawane pytania

W blokowaniu transakcja A czeka na zasób trzymany przez B, ale B nie czeka na A — B w końcu się zakończy i zwolni zasób. Deadlock to **cykliczne blokowanie**: A czeka na B i B czeka na A. SQL Server rozwiązuje deadlock automatycznie (błąd 1205), natomiast blokowanie może trwać dowolnie długo, dopóki właściciel nie zwolni zasobu.
Nie. SQL Server wycofuje (ROLLBACK) transakcję-ofiarę, przywracając dane do stanu sprzed jej rozpoczęcia. Żadne dane nie są tracone — aplikacja otrzymuje błąd 1205 i powinna ponowić transakcję. Integralność bazy pozostaje nienaruszona.
Uruchom zapytanie odczytujące ring buffer system_health (podane wyżej w sekcji diagnostycznej) — działa przez każde narzędzie obsługujące T-SQL: Azure Data Studio, sqlcmd, PowerShell (Invoke-SqlCmd). Alternatywnie, monitoruj licznik PerfMon `SQLServer:Locks > Number of Deadlocks/sec`.
Główna wada to zwiększone zużycie tempdb — SQL Server przechowuje wersje wierszy w tempdb, co przy intensywnych modyfikacjach może obciążyć ten magazyn. Dodatkowo aplikacje polegające na blokującym zachowaniu `READ COMMITTED` (np. oczekujące na zakończenie innej transakcji przed odczytem) mogą wymagać dostosowania logiki.
Nie. Optimized Locking znacząco redukuje ryzyko deadlocków, ale nie eliminuje ich całkowicie — deadlocki wciąż mogą wystąpić na zasobach takich jak wątki robocze, pamięć czy rywalizacja o Transaction ID (TID). Mechanizm jest jednak najskuteczniejszą dotychczasową optymalizacją Microsoftu w tym obszarze.
Odczytaj raporty z system_health, wyodrębnij pole `inputbuf` z każdego procesu i pogrupuj. Możesz też użyć narzędzia **sp_BlitzLock** z First Responder Kit Brent Ozara, które parsuje system_health i przedstawia zagregowane statystyki — które zapytania, tabele i indeksy pojawiają się najczęściej.
Nie da się ich w 100% wyeliminować w systemie ze współbieżnymi transakcjami — to nieodłączna cecha każdej relacyjnej bazy danych z blokadami. Można jednak zredukować ich częstotliwość do poziomu marginalnego, stosując RCSI, Optimized Locking, krótkie transakcje i ustandaryzowaną kolejność dostępu do obiektów. ---

Czy ten artykuł był pomocny?