block

Snippet Name: block

Tags: helpful,scriptgeneration

Created Date: Oct 1 2021 8:05AM
Last Modified Date: Apr 1 2022 11:22AM

–desc: produces a tree like structure of current blocking tree with the main blockers marked as HEAD:

Dependencies: none-standalone code

This is one of my go to procedures it produces a quick visual representation of it the blocking tree and the only information I need including generating a hopeful kill statement to fix and identify any blocking that may have been gone on for hours there’s a cute little expansion to show these hours minutes seconds so you know how long it was going on.

Sample Output:

 
  --desc: produces a tree like structure of current blocking tree with the main blockers marked as HEAD: 
 
 
 
 SET NOCOUNT ON 
 
 GO
 
 SELECT 
 
   ElapsedTime = dt.days + ':' + dt.Hours + ':' + dt.Minutes + ':' + dt.Seconds,
 
   [R].[spid], 
 
   [R].[blocked],
 
   [R].[nt_username],
 
   QUOTENAME(OBJECT_SCHEMA_NAME(t.[objectid],t.[dbid])) 
 
   + '.' 
 
   + QUOTENAME(OBJECT_NAME(t.[objectid],t.[dbid])) AS ObjectName,
 
   REPLACE (REPLACE ([T].[text], CHAR(10), ' '), CHAR (13), ' ' ) AS BATCH
 
 INTO #T
 
 FROM [sys].[sysprocesses] R 
 
 CROSS APPLY [sys].[dm_exec_sql_text]([R].[sql_handle]) T
 
     CROSS APPLY(SELECT [Days]          = RIGHT('000' + CONVERT(VARCHAR(128),datepart(day,GETDATE() - r.[last_batch])-1),2),
 
                        [Hours]         = RIGHT('000' + CONVERT(VARCHAR(128),DATEPART(Hour,GETDATE() - r.[last_batch])),2),
 
                        [Minutes]       = RIGHT('000' + CONVERT(VARCHAR(128),datepart(Minute,GETDATE() - r.[last_batch])),2),
 
                        [Seconds]       = RIGHT('000' +CONVERT(VARCHAR(128),datepart(Second,GETDATE() - r.[last_batch])),2)
 
                ) dt
 
 GO
 
 WITH BLOCKERS (ElapsedTime,SPID, BLOCKED, nt_username,ObjectName,LEVEL, BATCH)
 
 AS
 
 (
 
 SELECT R.ElapsedTime,
 
 [R].[spid],
 
 [R].[blocked],
 
 R.[nt_username],
 
 R.ObjectName,
 
 CAST (REPLICATE ('0', 4-LEN (CAST ([R].[spid] AS VARCHAR))) + CAST ([R].[spid] AS VARCHAR) AS VARCHAR (1000)) AS LEVEL,
 
 [R].[BATCH] FROM #T R
 
 WHERE ([R].[blocked] = 0 OR [R].[blocked] = [R].[spid])
 
 AND EXISTS (SELECT * FROM #T R2 WHERE [R2].[blocked] = [R].[spid] AND [R2].[blocked] <> [R2].[spid])
 
 UNION ALL
 
 SELECT R.ElapsedTime,[R].[spid],
 
 [R].[blocked],
 
 R.[nt_username],
 
 R.ObjectName,
 
 CAST ([BLOCKERS].[LEVEL] + RIGHT (CAST ((1000 + [R].[spid]) AS VARCHAR (100)), 4) AS VARCHAR (1000)) AS LEVEL,
 
 [R].[BATCH] FROM #T AS R
 
 INNER JOIN BLOCKERS ON [R].[blocked] = [BLOCKERS].[SPID] WHERE [R].[blocked] > 0 AND [R].[blocked] <> [R].[spid]
 
 )
 
 SELECT ElapsedTime,[BLOCKERS].[SPID],[BLOCKERS].[nt_username],ISNULL(ObjectName,'==Inline SQL Text ==') AS ObjectName,N'    ' + REPLICATE (N'|         ', LEN ([BLOCKERS].[LEVEL])/4 - 1) +
 
 CASE WHEN (LEN([BLOCKERS].[LEVEL])/4 - 1) = 0
 
 THEN 'HEAD -  '
 
 ELSE '|------  ' END
 
 + CAST ([BLOCKERS].[SPID] AS NVARCHAR (10)) + N' ' + [BLOCKERS].[BATCH] AS BLOCKING_TREE
 
 FROM BLOCKERS ORDER BY [BLOCKERS].[LEVEL] ASC
 
 GO
 
 DROP TABLE #T
 
 GO
 
 

Leave a Reply