DeadlockCollector – dtcSoftware

🔒 DeadlockCollector

Automatische Erfassung und Analyse von SQL Server Deadlocks · dtcSoftware · Janke

SQL Server 2008 R2+ Kein XEvent-Setup nötig AlwaysOn-kompatibel 2 SQL-Scripts
📋 Übersicht
⚙️ Installation
🗄️ Datenbankobjekte
🔍 Analyse-Queries

Deadlocks automatisch sammeln — ohne Konfiguration

Der DeadlockCollector nutzt die System Health Extended Event Session, die auf jedem SQL Server ab 2008 R2 immer aktiv ist. Ein stündlicher SQL Agent Job liest den Ring Buffer, parst die Deadlock-Graphen und schreibt strukturierte Daten dauerhaft in eine eigene Datenbank.

Kein Trace · kein Profiler Langzeit-Historie Duplikat-Schutz via Hash AG Secondary-aware
⚡ Funktionsweise
System Health XEvent Ring Buffer
immer aktiv
dbo.Collect SQL Agent Job
stündlich
dbo.InsertDeadLock XML parsen
Hash-Duplikatschutz
dbo.DeadLock persistente Tabelle
strukturiert
5 Views Tag · Stunde · Muster
Analyse
Der SQL Server schreibt Deadlock-Ereignisse als XML in den Ring Buffer der System Health Session. Dieser wird stündlich ausgelesen — alle neuen Ereignisse seit dem letzten Lauf werden extrahiert, geparst und strukturiert gespeichert. So entsteht eine lückenlose Langzeit-Historie, die der Ring Buffer allein nicht leisten kann.
✅ Vorteile im Überblick

🚫 Kein Trace / kein Profiler

Ausschließlich die immer-aktive System Health Session. Kein zusätzlicher XEvent-Setup, kein messbarer Performance-Impact.

📅 Langzeit-Historie

Der Ring Buffer überschreibt sich laufend. Diese Datenbank speichert Deadlocks dauerhaft — für Trend-Analyse über Wochen und Monate.

🔁 Duplikat-Schutz

Jeder Deadlock wird per SHA-Hash aus Zeitstempel und Graph-Inhalt eindeutig identifiziert. Mehrfachausführung ist sicher.

🏗️ AlwaysOn-aware

dbo.Collect prüft den Updateability-Status — auf einem AG Secondary (READ_ONLY) wird der Job automatisch übersprungen.

📊 Erfasste Felder pro Deadlock
KategorieFelder
ZeitstempelEvent_DateTime — timezone-korrigiert aus XEvent-Timestamp
Beteiligte ProzesseAffectedProcesses, SPID_1/2, LoginName_1/2, App_Name_1/2, HostName_1/2
SQL-KontextSQLText_1/2 aus dm_exec_sql_text, ProcedureName_1/2 aus ExecutionStack, InputBuffer_1/2
Lock-DetailsWaitResource_1/2, LockMode_1/2, IsolationLevel_1/2, DatabaseName_1/2
Query-PläneQueryPlan_1/2 aus dm_exec_query_plan, SQLHandle_1/2, PlanHandle_1/2
Vollständiger GraphComplete_DeadlockGraph (XML), berechnete Spalten: Victim_List, Process_List_ExecutionStack, Resource_List
⚙️ Installation
Beide Scripts müssen als sysadmin ausgeführt werden. Die Datenbank wird auf der Standarddateigruppe der Instanz angelegt.
  1. Script 1 ausführen: Datenbank und Objekte anlegen

    SetUpDeadlockCollectorDb.sql auf der Zielinstanz ausführen. Erstellt Datenbank DeadlockCollector, Tabelle, alle Views und Stored Procedures.

  2. Script 2 ausführen: SQL Agent Job anlegen

    SetUpDeadlockCollectorJob.sql ausführen. Erstellt Job DeadlockCollector mit stündlichem Zeitplan.

  3. Ersten manuellen Lauf starten

    Job einmal manuell starten, um vorhandene Deadlocks aus dem Ring Buffer sofort zu erfassen.

  4. Ergebnis prüfen

    SELECT * FROM DeadlockCollector.dbo.vwvDeadlockInfos ORDER BY Event_DateTime DESC;

Job manuell starten und Ergebnis prüfen
-- Job manuell starten 
EXEC msdb.dbo.sp_start_job N'DeadlockCollector'; 
 
-- Ergebnis prüfen 
SELECT TOP 20 
Event_DateTime, 
DatabaseName_1, 
SQLText_1, 
SQLText_2, 
LockMode_1, 
LockMode_2, 
AffectedProcesses 
FROM DeadlockCollector.dbo.vwvDeadlockInfos 
ORDER BY Event_DateTime DESC;
Alte Einträge bereinigen
-- Deadlocks älter als ein bestimmtes Datum löschen 
DECLARE @removed int; 
 
EXEC DeadlockCollector.dbo.deleteDeadLock 
@DeleteOlderAs = '2026-01-01', 
@DeadlocksRemoved = @removed OUTPUT; 
 
SELECT @removed AS [Gelöschte Einträge];
Import aus XEvent-Datei (.xel)
-- Deadlocks aus gespeicherter XEvent-Datei importieren (ab SQL Server 2012) 
DECLARE @collected int; 
 
EXEC DeadlockCollector.dbo.InsertDeadLock 
@XESource = N'\\server\share\system_health*.xel', 
@DeadlocksCollected = @collected OUTPUT; 
 
SELECT @collected AS [Importierte Deadlocks];
🗄️ Alle Datenbankobjekte
dbo.DeadLock
Table · PK NONCLUSTERED · Fill Factor 90

Zentrale Tabelle. Eine Zeile pro Deadlock-Ereignis mit 35 Spalten inkl. berechneter XML-Spalten und Duplikat-Hash.

dbo.sel_xml_List
Function · SCHEMABINDING

Extrahiert victim-list, process-list oder resource-list aus dem Deadlock-XML. Wird als berechnete Spalte in dbo.DeadLock verwendet.

dbo.Collect
Stored Procedure · Einstiegspunkt

Prüft READ_ONLY-Status (AG Secondary), ruft InsertDeadLock auf und gibt Anzahl gesammelter Deadlocks zurück.

dbo.InsertDeadLock
Stored Procedure · Kernlogik

Liest Ring Buffer oder XEL-Datei, parst XML via XQuery, holt SQL-Text und Query-Plan aus DMVs. Duplikat-Filter via Hash.

dbo.deleteDeadLock
Stored Procedure · Bereinigung

Löscht Einträge älter als ein angegebenes Datum. OUTPUT-Parameter liefert Anzahl der entfernten Zeilen.

dbo.vwvDeadlockInfos
View · Basis

Alle Spalten aus dbo.DeadLock aufbereitet. Basisview für alle anderen Aggregations-Views.

dbo.vwvDeadLockByDay
View · Aggregation nach Tag

Anzahl Deadlocks, betroffene Prozesse und Opfer pro Datum und Wochentag.

dbo.vwvDeadLockByDayHour
View · Aggregation nach Stunde

Deadlocks pro Tag und Stunde — für Hotspot-Analyse: Wann treten Deadlocks gehäuft auf?

dbo.vwvDeadLockByDayAndDatabase
View · Aggregation nach DB

Deadlocks pro Tag und Datenbankkombination. Zeigt welche Datenbanken betroffen sind.

dbo.vwvDeadLockCombinationBySQLText
View · Muster-Erkennung

Häufigste SQL-Text-Kombinationen. Identifiziert systematisch wiederkehrende Deadlock-Muster.

Tabellen-Schema: dbo.DeadLock
SpalteTypBeschreibung
ID_DeadLockint IDENTITYPrimärschlüssel (NONCLUSTERED, Fill Factor 90)
Event_DateTimedatetime2(0)Ereigniszeitpunkt, timezone-korrigiert
AffectedProcessesintAnzahl beteiligter Prozesse
DatabaseName_1/2nvarchar(128)Datenbankname beider Prozesse via DB_NAME()
SQLText_1/2nvarchar(max)SQL-Text aus sys.dm_exec_sql_text
ProcedureName_1/2nvarchar(386)Prozedurname aus ExecutionStack[1].frame[1]
LoginName_1/2sysnameSQL/Windows-Login der beteiligten Sessions
SPID_1/2intSession-IDs
InputBuffer_1/2varchar(max)inputbuf aus Deadlock-Graph
App_Name_1/2sysnameAnwendungsname (clientapp)
HostName_1/2sysnameClient-Hostname
WaitResource_1/2varchar(500)Blockierte Ressource (Key / RID / Page)
LockMode_1/2varchar(10)Lock-Modus: S, X, U, IX …
IsolationLevel_1/2varchar(100)Transaktions-Isolationsstufe
QueryPlan_1/2xmlAusführungsplan aus sys.dm_exec_query_plan
Complete_DeadlockGraphxmlVollständiger Deadlock-XML-Graph
Victim_Listxml (computed)victim-list aus Complete_DeadlockGraph
Process_List_ExecutionStackxml (computed)process-list inkl. ExecutionStack
Resource_Listxml (computed)resource-list (Sperren-Details)
SQLHandle_1/2varbinary(64)SQL Handle für nachträgliche DMV-Abfragen
PlanHandle_1/2varbinary(64)Plan Handle für sys.dm_exec_query_plan
DeadlockHashvarbinary(42)SHA-Hash für Duplikat-Erkennung
🔍 Häufigkeit pro Tag
SELECT 
Date, 
Day, 
NumOccurances, 
AffectedProcesses, 
Victims 
FROM DeadlockCollector.dbo.vwvDeadLockByDay 
ORDER BY Date DESC;
🔍 Hotspots nach Tageszeit
SELECT 
Date, 
[Hour], 
NumOccurances, 
Sum_AffectedProcesses, 
Sum_Victims 
FROM DeadlockCollector.dbo.vwvDeadLockByDayHour 
WHERE NumOccurances > 0 
ORDER BY Date DESC, [Hour] ASC;
🔍 Wiederkehrende Muster erkennen
SELECT TOP 20 
NumOccurances, 
AffectedProcesses, 
LEFT(SQLText_1, 120) AS SQLText_1_Snippet, 
LEFT(SQLText_2, 120) AS SQLText_2_Snippet 
FROM DeadlockCollector.dbo.vwvDeadLockCombinationBySQLText 
ORDER BY NumOccurances DESC;
🔍 Betroffene Datenbanken
SELECT 
DatabaseName_1, 
DatabaseName_2, 
COUNT(*) AS NumDeadlocks, 
MIN(Event_DateTime) AS FirstSeen, 
MAX(Event_DateTime) AS LastSeen 
FROM DeadlockCollector.dbo.vwvDeadlockInfos 
GROUP BY DatabaseName_1, DatabaseName_2 
ORDER BY NumDeadlocks DESC;
🔍 Details der letzten 10 Deadlocks
SELECT TOP 10 
Event_DateTime, 
DatabaseName_1, 
LoginName_1, App_Name_1, 
LockMode_1, IsolationLevel_1, 
LEFT(SQLText_1, 200) AS SQLText_1, 
-- Beteiligter Prozess 2 
LoginName_2, 
LockMode_2, 
LEFT(SQLText_2, 200) AS SQLText_2 
FROM DeadlockCollector.dbo.vwvDeadlockInfos 
ORDER BY Event_DateTime DESC;
🔍 Vollständigen Deadlock-Graph öffnen
-- In SSMS: XML-Link anklicken → Deadlock-Diagramm wird gerendert 
SELECT TOP 1 
Event_DateTime, 
Complete_DeadlockGraph, 
Victim_List, 
Resource_List 
FROM DeadlockCollector.dbo.vwvDeadlockInfos 
ORDER BY Event_DateTime DESC;
🔍 30-Tage-Trend mit gleitendem Durchschnitt
SELECT 
Date, 
Day, 
NumOccurances, 
AVG(NumOccurances) OVER ( 
ORDER BY Date 
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW 
) AS Avg7Days 
FROM DeadlockCollector.dbo.vwvDeadLockByDay 
WHERE Date >= DATEADD(day, -30, CAST(GETDATE() AS date)) 
ORDER BY Date ASC;
🔍 Deadlocks nach Login und Anwendung
SELECT 
COALESCE(LoginName_1, LoginName_2) AS Login, 
COALESCE(App_Name_1, App_Name_2) AS Application, 
COUNT(*) AS NumDeadlocks 
FROM DeadlockCollector.dbo.vwvDeadlockInfos 
GROUP BY 
COALESCE(LoginName_1, LoginName_2), 
COALESCE(App_Name_1, App_Name_2) 
ORDER BY NumDeadlocks DESC;