🔒 DeadlockCollector
Automatische Erfassung und Analyse von SQL Server Deadlocks · dtcSoftware · Janke
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.
immer aktiv
stündlich
Hash-Duplikatschutz
strukturiert
Analyse
🚫 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.
| Kategorie | Felder |
|---|---|
| Zeitstempel | Event_DateTime — timezone-korrigiert aus XEvent-Timestamp |
| Beteiligte Prozesse | AffectedProcesses, SPID_1/2, LoginName_1/2, App_Name_1/2, HostName_1/2 |
| SQL-Kontext | SQLText_1/2 aus dm_exec_sql_text, ProcedureName_1/2 aus ExecutionStack, InputBuffer_1/2 |
| Lock-Details | WaitResource_1/2, LockMode_1/2, IsolationLevel_1/2, DatabaseName_1/2 |
| Query-Pläne | QueryPlan_1/2 aus dm_exec_query_plan, SQLHandle_1/2, PlanHandle_1/2 |
| Vollständiger Graph | Complete_DeadlockGraph (XML), berechnete Spalten: Victim_List, Process_List_ExecutionStack, Resource_List |
-
Script 1 ausführen: Datenbank und Objekte anlegen
SetUpDeadlockCollectorDb.sqlauf der Zielinstanz ausführen. Erstellt DatenbankDeadlockCollector, Tabelle, alle Views und Stored Procedures. -
Script 2 ausführen: SQL Agent Job anlegen
SetUpDeadlockCollectorJob.sqlausführen. Erstellt JobDeadlockCollectormit stündlichem Zeitplan. -
Ersten manuellen Lauf starten
Job einmal manuell starten, um vorhandene Deadlocks aus dem Ring Buffer sofort zu erfassen.
-
Ergebnis prüfen
SELECT * FROM DeadlockCollector.dbo.vwvDeadlockInfos ORDER BY Event_DateTime DESC;
-- 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;
-- 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];
-- 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];
Zentrale Tabelle. Eine Zeile pro Deadlock-Ereignis mit 35 Spalten inkl. berechneter XML-Spalten und Duplikat-Hash.
Extrahiert victim-list, process-list oder resource-list aus dem Deadlock-XML. Wird als berechnete Spalte in dbo.DeadLock verwendet.
Prüft READ_ONLY-Status (AG Secondary), ruft InsertDeadLock auf und gibt Anzahl gesammelter Deadlocks zurück.
Liest Ring Buffer oder XEL-Datei, parst XML via XQuery, holt SQL-Text und Query-Plan aus DMVs. Duplikat-Filter via Hash.
Löscht Einträge älter als ein angegebenes Datum. OUTPUT-Parameter liefert Anzahl der entfernten Zeilen.
Alle Spalten aus dbo.DeadLock aufbereitet. Basisview für alle anderen Aggregations-Views.
Anzahl Deadlocks, betroffene Prozesse und Opfer pro Datum und Wochentag.
Deadlocks pro Tag und Stunde — für Hotspot-Analyse: Wann treten Deadlocks gehäuft auf?
Deadlocks pro Tag und Datenbankkombination. Zeigt welche Datenbanken betroffen sind.
Häufigste SQL-Text-Kombinationen. Identifiziert systematisch wiederkehrende Deadlock-Muster.
| Spalte | Typ | Beschreibung |
|---|---|---|
ID_DeadLock | int IDENTITY | Primärschlüssel (NONCLUSTERED, Fill Factor 90) |
Event_DateTime | datetime2(0) | Ereigniszeitpunkt, timezone-korrigiert |
AffectedProcesses | int | Anzahl beteiligter Prozesse |
DatabaseName_1/2 | nvarchar(128) | Datenbankname beider Prozesse via DB_NAME() |
SQLText_1/2 | nvarchar(max) | SQL-Text aus sys.dm_exec_sql_text |
ProcedureName_1/2 | nvarchar(386) | Prozedurname aus ExecutionStack[1].frame[1] |
LoginName_1/2 | sysname | SQL/Windows-Login der beteiligten Sessions |
SPID_1/2 | int | Session-IDs |
InputBuffer_1/2 | varchar(max) | inputbuf aus Deadlock-Graph |
App_Name_1/2 | sysname | Anwendungsname (clientapp) |
HostName_1/2 | sysname | Client-Hostname |
WaitResource_1/2 | varchar(500) | Blockierte Ressource (Key / RID / Page) |
LockMode_1/2 | varchar(10) | Lock-Modus: S, X, U, IX … |
IsolationLevel_1/2 | varchar(100) | Transaktions-Isolationsstufe |
QueryPlan_1/2 | xml | Ausführungsplan aus sys.dm_exec_query_plan |
Complete_DeadlockGraph | xml | Vollständiger Deadlock-XML-Graph |
Victim_List | xml (computed) | victim-list aus Complete_DeadlockGraph |
Process_List_ExecutionStack | xml (computed) | process-list inkl. ExecutionStack |
Resource_List | xml (computed) | resource-list (Sperren-Details) |
SQLHandle_1/2 | varbinary(64) | SQL Handle für nachträgliche DMV-Abfragen |
PlanHandle_1/2 | varbinary(64) | Plan Handle für sys.dm_exec_query_plan |
DeadlockHash | varbinary(42) | SHA-Hash für Duplikat-Erkennung |
SELECT Date, Day, NumOccurances, AffectedProcesses, Victims FROM DeadlockCollector.dbo.vwvDeadLockByDay ORDER BY Date DESC;
SELECT Date, [Hour], NumOccurances, Sum_AffectedProcesses, Sum_Victims FROM DeadlockCollector.dbo.vwvDeadLockByDayHour WHERE NumOccurances > 0 ORDER BY Date DESC, [Hour] ASC;
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;
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;
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;
-- 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;
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;
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;