-- =================================================================================================================== -- SQLI-DLK-001: Deadlocks -- =================================================================================================================== -- Regel-id: SQLI-DLK-001 -- Titel: Deadlocks -- Alvor: Medium; High fra 10 deadlocks siden sidste måling. -- Versioner: SQL Server 2008 og nyere (system_health). 2012+: event-filerne; 2008/2008 R2: ring buffer. SQL Server -- 2005: "tjek manuelt" (trace flag 1222). -- -- Hvad tjekkes, og hvorfor: -- Om der er sket deadlocks siden forrige måling. -- -- Vurdering (sker i C# ud fra de indsamlede data, ikke i SQL'en, medmindre andet er nævnt): -- xml_deadlock_report-hændelser fra system_health parses i C#. Første gang tages kun det seneste døgn med; derefter -- læses videre fra seneste fil og offset. Agentens egne deadlocks (program 'SQLInsight Pro') tælles ikke. Fund når -- der er nye deadlocks; de seneste 3 vises med processer. -- -- Grænseværdier (konfigurationsnøgle i agentens appsettings.json og standardværdi): -- Ingen (High fra 10, fast i koden). -- -- Rettigheder til agentens login (se db/permissions/grant-least-privilege.sql; [agent] = agentens login): -- GRANT VIEW SERVER STATE TO [agent]; -- SQL Server 2005-2019 -- GRANT VIEW SERVER PERFORMANCE STATE TO [agent]; -- SQL Server 2022+ (erstatter VIEW SERVER STATE) -- GRANT VIEW SERVER SECURITY STATE TO [agent]; -- SQL Server 2022+ -- -- Data kommer fra (collector, fil : medlemmer, interval): -- DeadlockCollector -- Fil: src/SQLInsight.Collectors/Concurrency/DeadlockCollector.cs -- Medlemmer: DeadlockCollector.BuildFileSql(lastFile: null, lastOffset: null), DeadlockCollector.RingBufferSql -- Interval: 5 min som standard (SQLInsight:CollectorIntervals:deadlocks) -- Delt script: SQL Scripts/_collectors/DeadlockCollector.sql -- Regelkode: src/SQLInsight.Rules/Concurrency/ConcurrencyRules.cs : DeadlockRule.Evaluate -- -- Read-only: Ja: kun SELECT (sys.fn_xe_file_target_read_file og DMV'er) samt SET-sessionsindstillinger. Ingen -- temp-tabeller; læsepositionen findes med ROW_NUMBER() i samme forespørgsel. -- Kørsel: Kør i SSMS som agentens login (eller et login med samme rettigheder). Hver variant er sin egen batch -- (GO); en variant for en anden SQL Server-version end din kan fejle - det er forventet. -- Per-database-forespørgsler er vist for databasen msdb, som findes overalt: ret navnet til den -- database, du vil se. -- =================================================================================================================== -- ------------------------------------------------------------------------------------------------------------------- -- Forbindelsen: Sessionsindstillinger, agenten sætter på hver forbindelse -- ------------------------------------------------------------------------------------------------------------------- -- Variant: Alle versioner: sættes på hver forbindelse, agenten åbner -- Kilde: SqlConnectionFactory.SessionSettings -- Kode: src/SQLInsight.Connectivity/SqlConnectionFactory.cs : SqlConnectionFactory.SessionSettings SET LOCK_TIMEOUT 5000; SET DEADLOCK_PRIORITY LOW; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; GO -- ------------------------------------------------------------------------------------------------------------------- -- DeadlockCollector: Nye deadlock-grafer (xml_deadlock_report) fra den indbyggede system_health-session. -- ------------------------------------------------------------------------------------------------------------------- -- Variant: SQL Server 2012 og nyere (system_health-filer; første læsning) -- Kilde: DeadlockCollector.BuildFileSql -- Kode: src/SQLInsight.Collectors/Concurrency/DeadlockCollector.cs : DeadlockCollector.BuildFileSql(lastFile: null, lastOffset: null) SELECT e.event_data, e.file_name, e.file_offset, e.rn FROM ( SELECT CASE WHEN object_name = N'xml_deadlock_report' THEN CAST(event_data AS nvarchar(max)) END AS event_data, file_name, file_offset, ROW_NUMBER() OVER (ORDER BY file_name DESC, file_offset DESC) AS rn FROM sys.fn_xe_file_target_read_file(N'system_health*.xel', NULL, NULL, NULL) ) AS e WHERE e.event_data IS NOT NULL OR e.rn = 1; GO -- Variant: SQL Server 2008 – 2008 R2, og når event-filerne ikke kan læses -- Kilde: DeadlockCollector.RingBufferSql -- Kode: src/SQLInsight.Collectors/Concurrency/DeadlockCollector.cs : DeadlockCollector.RingBufferSql SELECT CAST(t.target_data AS nvarchar(max)) FROM sys.dm_xe_session_targets t JOIN sys.dm_xe_sessions s ON s.address = t.event_session_address WHERE s.name = N'system_health' AND t.target_name = N'ring_buffer' GO