Skip to content

Instantly share code, notes, and snippets.

@fvclaus
Created May 20, 2022 15:35
Show Gist options
  • Save fvclaus/392b193677052c379d8b74f3ae876b53 to your computer and use it in GitHub Desktop.
Save fvclaus/392b193677052c379d8b74f3ae876b53 to your computer and use it in GitHub Desktop.
MSSQL SQL Server How to analyze and solve deadlocks

We start by looking at all current locks:

SELECT txt.text, 
  sysprocesses.spid,
  sysprocesses.blocked,
  CASE
      WHEN resource_type = 'OBJECT'
          THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id)
       ELSE OBJECT_NAME(partitions.OBJECT_ID)
  END AS ObjectName,
  indexes.name AS index_name,
  dm_tran_locks.request_mode,
  dm_tran_locks.request_status,
  CASE
    WHEN resource_type = 'KEY'
      THEN 'ROW IN INDEX'
    ELSE resource_type
  END as resource_type,
  dm_tran_locks.resource_description
FROM sys.sysprocesses
LEFT OUTER JOIN sys.dm_exec_connections ON dm_exec_connections.session_id = sysprocesses.spid
    OUTER APPLY sys.dm_exec_sql_text(dm_exec_connections.most_recent_sql_handle)  AS txt
LEFT OUTER JOIN sys.dm_tran_locks ON dm_tran_locks.request_session_id = sysprocesses.spid
LEFT OUTER JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id
LEFT JOIN sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID AND indexes.index_id = partitions.index_id
WHERE dm_tran_locks.resource_type <> 'DATABASE'
ORDER BY sysprocesses.spid, ObjectName, index_name, resource_type;

image

We can see that process 54 (spid) is waiting (request_status=WAIT) for lock on a row in an index that is currently held by process 57 (blocked). We can also see the SQL (text) of process 54 that caused SQL Server to acquire a lock. Looking at process 57, we see the lock process 54 is waiting on:

image

We know it is the lock where are looking for, because it has the same object- and index name and the same resource description, which in this case is used to identify the row in the table. We can resolve the resource description to the actual row using this query:

SELECT %%lockres%%, *
FROM <TABLE_NAME> WITH(NOLOCK)
WHERE %%lockres%% IN
(
SELECT l.resource_description
FROM sys.dm_tran_locks as l
WHERE l.resource_type IN ('KEY', 'RID') --index lock, KEY
);

image

The above example does not depict a dead lock situation, because process 57 is not blocked by another process. In dead lock scenario, you would have to follow the blocked column until you arrive at your starting process. Know you know what process (transaction) is holding locks on which rows (or tables) and can fix it be reordering statements or changing the transaction isolation level.

Links and credits:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment