Wednesday, April 11, 2018

Capturing and decrypting Deadlock information from SQL Server Part 1


Capturing and decoding Deadlock information from SQL Server Part 1


We will have two articles in this series.
1. Different ways to capture deadlock
2. Decoding deadlock data from captured deadlock data

I know this is very common issue which DBA might not be able to completely resolve but DBA can provide detailed information regarding Deadlock.

Let us see what are the different ways we can capture deadlock data from SQL Server.

From SQL Server 2012 onwards we can capture deadlock data directly from System Health Extended event session, for this we don’t need enable any trace flags.
Earlier to SQL Server 2012, we need to enable flags 1204 and 1222 to get detailed deadlock information.
You can check my blog to find how to enable trace flags.

Below is the script to capture deadlock, This code is robust enough to check for SQL Server version, to get data from System health Event session or from SQL Server error log. If it does not find any information it will give suggestions as well.

SET NOCOUNT ON
DECLARE @stDate AS DATETIME = '2016-06-13 04:49:26'                                --Please key in the UTC time at which alert created
DECLARE @DecelockText AS VARCHAR (100) = 'Process ID 113'     --Replace 113 with the process ID part of deadlock

DECLARE @endDate AS DATETIME
SELECT @stDate = DATEADD(MILLISECOND,DATEDIFF(MILLISECOND,getutcdate(),GETDATE()),@stDate)
SET @endDate = DATEADD(MINUTE, 1, @stDate)
SET @stDate  = DATEADD(MINUTE, -2, @stDate)


IF (CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - 1) + '.' + REPLACE(RIGHT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)))),'.','') AS numeric(18,10)) ) >= 11
BEGIN
                DECLARE @PATH VARCHAR(500)
                SELECT  @PATH= [path] FROM sys.dm_os_server_diagnostics_log_configurations WITH (NOLOCK) OPTION (RECOMPILE);

                SET @PATH = @PATH + 'system_health*.xel'

                CREATE TABLE #Deadloc_Trace (DLGraph XML, Execution_time datetime)

                INSERT INTO #Deadloc_Trace

                SELECT CONVERT(xml, event_data).query('/event/data/value/child::*'),
                                   CONVERT(xml, event_data).value('(event[@name="xml_deadlock_report"]/@timestamp)[1]','datetime') as Execution_Time
                FROM sys.fn_xe_file_target_read_file(@PATH, null, null, null)

                WHERE object_name like 'xml_deadlock_report'


                SELECT * FROM  #Deadloc_Trace WHERE Execution_Time BETWEEN @stDate and @endDate

                DROP TABLE #Deadloc_Trace
END
ELSE
                BEGIN
                CREATE TABLE #TraceStatus(
                TraceFlag varchar(100)
                , [Status] int
                , [Global] int
                ,  [Session] int)

                insert #TraceStatus(TraceFlag, [Status], [Global], [Session])
                EXEC('DBCC TRACESTATUS(1204,1222) WITH NO_INFOMSGS;')
               
                IF EXISTS (select * from #TraceStatus where Global > 0)
                BEGIN
                                CREATE TABLE #ErrLog(LogDate datetime, ProcessInfo sysname, LogText nvarchar(1000));

                                INSERT INTO #ErrLog
                                EXEC xp_readerrorlog 0, 1, @DecelockText;

                                SELECT TOP 1 @stDate = LogDate
                                FROM #ErrLog
                                ORDER BY LogDate DESC;

                                SET @endDate = DATEADD(minute,2,@stDate)

                                --select @stDate, @endDate

                                EXEC master.dbo.xp_readerrorlog 0, 1, null, null,@stDate, @endDate

                                DROP TABLE #ErrLog;
                END
                ELSE
                BEGIN
                                PRINT 'Currently deadlock traces are not enabled and hence we cannot gather more information.
                We need to enable Deadlock traces 1204,1222 to capture deadlock information in future.
                '
                END

                DROP TABLE #TraceStatus;
END


Hope this helps someone thanks for checking in.


No comments:

Post a Comment

Configure a Linux Service to Start Automatically After a Crash or Reboot

Configure a Linux Service to Start Automatically After a Crash or Reboot Below articles defines how to start a service automatically after ...