Deadlock

Rédigé par Sozezzo - - Aucun commentaire

We have same SQL Scripts to try to find out about what it happens when we have or had deadlocks.

 

  • Get current running commands.
  • Create event to find blocked processes and deadlocks.

 

Sources :

Deadlocking
https://technet.microsoft.com/en-us/library/ms177433%28v=sql.105%29.aspx

How to isolate the current running commands in SQL Server
https://www.mssqltips.com/sqlservertip/1811/how-to-isolate-the-current-running-commands-in-sql-server/

How To Monitor Deadlocks in SQL Server
http://blogs.technet.com/b/mspfe/archive/2012/06/28/how_2d00_to_2d00_monitor_2d00_deadlocks_2d00_in_2d00_sql_2d00_server.aspx

A very quick guide to deadlock diagnosis in SQL Server
https://dzone.com/articles/very-quick-guide-deadlock

Finding Blocked Processes and Deadlocks using SQL Server Extended Events
http://www.brentozar.com/archive/2014/03/extended-events-doesnt-hard/#comments

 

* Get current running commands

PRINT '-- Get current running commands';
-- current running commands
SELECT
      @@servername AS ServerName
    , GetDate() AS LocalDate
    , sder.session_id AS [SPID]
    , sdes.login_name AS [Login]
    , sd.name AS [DBName]
    , sder.start_time AS [Start Time]
    , sder.status AS [Status]
    , sder.percent_complete AS [Pct Cmplt]
    , sder.estimated_completion_time AS [Est Cmplt Time]
    , sder.wait_type AS [Wait Type]
    , sder.wait_time AS [Wait Time]
    , sder.last_wait_type AS [Last Wait]
    , sder.cpu_time AS [CPU Time]
    , sder.total_elapsed_time AS [Total Elpsd Time]
    , sder.reads AS [Reads]
    , sder.writes AS [Writes]
    , sder.logical_reads AS [Logical Reads]
    , Stuff((
    SELECT
        ', ' + v.NAME
    FROM       sys.dm_exec_plan_attributes(sder.plan_handle) AS pa
    INNER JOIN master..spt_values  v  ON v.type = 'sop' -- Set OPtions I guess
            AND v.number & Cast(pa.value AS INT) = v.number
        WHERE
            attribute =
            'set_options'
    FOR XML PATH('')
    ), 1, 13, '') AS [Set Options]
    , sder.command AS [Command]
    , sdet.text AS [SQL Text]
    , CASE WHEN SDER.[statement_start_offset] > 0 THEN
        --The start of the active command is not at the beginning of the full command text
        CASE SDER.[statement_end_offset] WHEN -1 THEN
            --The end of the full command is also the end of the active statement
            SUBSTRING(sdet.TEXT, (SDER.[statement_start_offset]/2) + 1, 2147483647)
                                                 ELSE
            --The end of the active statement is not at the end of the full command
            SUBSTRING(sdet.TEXT, (SDER.[statement_start_offset]/2) + 1, (SDER.[statement_end_offset] - SDER.[statement_start_offset])/2) END
                                                  ELSE
        --1st part of full command is running
        CASE SDER.[statement_end_offset] WHEN -1 THEN
            --The end of the full command is also the end of the active statement
            RTRIM(LTRIM(sdet.[text]))
                                                 ELSE
            --The end of the active statement is not at the end of the full command
            LEFT(sdet.TEXT, (SDER.[statement_end_offset]/2) +1) END END AS [executing statement]
FROM        sys.dm_exec_Requests                sder
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sdet
JOIN        sys.dm_exec_sessions                sdes ON sder.session_id = sdes.session_id
JOIN        sys.databases                       sd   ON sder.database_id = sd.database_id
    WHERE
        sder.session_id <> @@SPID

 

 

* Create event to find blocked processes and deadlocks.

!! Make sure this path exists before you start the trace !!

-- !! Make sure this path exists before you start the trace !!
CREATE EVENT SESSION [blocked_process] ON SERVER
ADD EVENT sqlserver.blocked_process_report(
    ACTION(sqlserver.client_app_name,
           sqlserver.client_hostname,
           sqlserver.database_name)) ,
ADD EVENT sqlserver.xml_deadlock_report (
    ACTION(sqlserver.client_app_name,
           sqlserver.client_hostname,
           sqlserver.database_name))
ADD TARGET package0.asynchronous_file_target
(SET filename = N'c:\XEventSessions\blocked_process.xel',
     metadatafile = N'c:\XEventSessions\blocked_process.xem',
     max_file_size=(65536),
     max_rollover_files=5)
WITH (MAX_DISPATCH_LATENCY = 5SECONDS)
GO

Change configuration - enable 'blocked process threshold'

/* Enabled to show advanced options */
EXEC sp_configure 'show advanced options', 1 ;
GO
RECONFIGURE ;
GO
/* Enabled the blocked process report */
EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE
GO
/* Start the Extended Events session */
ALTER EVENT SESSION [blocked_process] ON SERVER
STATE = START;


Read data from events


DECLARE @xel nvarchar(1024);  -- log filename
DECLARE @xem nvarchar(1024);  -- Meatadata file
DECLARE @x   nvarchar(1024);  -- temp variable
SELECT  @x = CAST(sys.server_event_session_fields.value as nvarchar(1024))
FROM sys.server_event_session_fields INNER JOIN sys.server_event_sessions
ON sys.server_event_session_fields.event_session_id = sys.server_event_sessions.event_session_id
WHERE sys.server_event_session_fields.name = N'filename' AND sys.server_event_sessions.name = N'blocked_process'
SET @x = SUBSTRING(@x ,  1, LEN(@x)-4)
SET @xem = @x+'*.xem';
SET @xel = @x+'*.xel';

WITH events_cte AS (
    SELECT
    xevents.event_data,
    DATEADD(mi,
    DATEDIFF(mi, GETUTCDATE(), CURRENT_TIMESTAMP),
    xevents.event_data.value('(event/@timestamp)[1]', 'datetime2')) AS [event time] ,
    xevents.event_data.value('(event/action[@name="client_app_name"]/value)[1]', 'nvarchar(128)') AS [client app name],
    xevents.event_data.value('(event/action[@name="client_hostname"]/value)[1]', 'nvarchar(max)') AS [client host name],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="database_name"]/value)[1]', 'nvarchar(max)') AS [database name],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="database_id"]/value)[1]', 'int') AS [database_id],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="object_id"]/value)[1]', 'int') AS [object_id],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="index_id"]/value)[1]', 'int') AS [index_id],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="duration"]/value)[1]', 'bigint') / 1000 AS [duration (ms)],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="lock_mode"]/text)[1]', 'varchar') AS [lock_mode],
    xevents.event_data.value('(event[@name="blocked_process_report"]/data[@name="login_sid"]/value)[1]', 'int') AS [login_sid],
    xevents.event_data.query('(event[@name="blocked_process_report"]/data[@name="blocked_process"]/value/blocked-process-report)[1]') AS blocked_process_report,
    xevents.event_data.query('(event/data[@name="xml_report"]/value/deadlock)[1]') AS deadlock_graph
    FROM    sys.fn_xe_file_target_read_file (@xel, @xem, null, null)
    CROSS APPLY (SELECT CAST(event_data AS XML) AS event_data) as xevents
)
SELECT
    CASE WHEN blocked_process_report.value('(blocked-process-report[@monitorLoop])[1]', 'nvarchar(max)') IS NULL
        THEN 'Deadlock'
        ELSE 'Blocked Process'
        END AS ReportType,
    [event time],
    CASE [client app name] WHEN '' THEN ' -- N/A -- '
                            ELSE [client app name]
                            END AS [client app _name],
    CASE [client host name] WHEN '' THEN ' -- N/A -- '
                            ELSE [client host name]
                            END AS [client host name],
    [database name],
    COALESCE(OBJECT_SCHEMA_NAME(object_id, database_id), ' -- N/A -- ') AS [schema],
    COALESCE(OBJECT_NAME(object_id, database_id), ' -- N/A -- ') AS [table],
    index_id,
    [duration (ms)],
    lock_mode,
    COALESCE(SUSER_NAME(login_sid), ' -- N/A -- ') AS username,
    CASE WHEN blocked_process_report.value('(blocked-process-report[@monitorLoop])[1]', 'nvarchar(max)') IS NULL
        THEN deadlock_graph
        ELSE blocked_process_report
        END AS Report
FROM events_cte
ORDER BY [event time] DESC ;

 

Les commentaires sont fermés.