IF EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID('dbo.find_blocker') AND sysstat & 0xf = 4) DROP PROCEDURE dbo.find_blocker GO CREATE PROCEDURE find_blocker AS /* Query to find spids at head of a blocking chain, their input buffers, and the type of blocking locks they hold */ DECLARE @blocker_spid smallint, @spid SMALLINT, @i_buff_string char(30), @CMD VARCHAR(255) SET NOCOUNT ON /* Get all blocked spids */ SELECT DISTINCT spid, suid, dbid, blocked INTO #blk FROM master..sysprocesses (NOLOCK) WHERE blocked <> 0 OR (spid IN (SELECT blocked FROM master..sysprocesses where blocked <> 0) AND blocked = 0) /* list all blocked spids */ SELECT "Blocked Processes" SELECT spid as "BLOCKED SPID", SUSER_NAME(suid) as "LOGIN NAME", DB_NAME(dbid) as "DB NAME", blocked as "BLOCKING SPID" FROM #blk WHERE blocked <> 0 /* dump all input buffers for spids that are blocked */ SELECT "Last Command from Blocked Processes" SELECT @spid = (SELECT MIN(spid) FROM #blk WHERE blocked <> 0) WHILE @spid IS NOT NULL BEGIN SELECT @CMD = 'SELECT "BLOCKED SPID ' + CONVERT(VARCHAR(3),@spid) + '"' + " DBCC INPUTBUFFER(" + CONVERT(VARCHAR(3),@spid) + ") " EXEC (@CMD) SELECT @spid = (SELECT MIN(spid) FROM #blk WHERE spid > @spid AND blocked <> 0) END /* For each spid at the head of a blocking chain print the type of blocking locks it holds */ /* dump all input buffers for spids that are blocked */ SELECT "Locks held by involved processes" SELECT spid, l.type, locktype = name, table_id = id, page, dbid FROM master..syslocks l, master.dbo.spt_values v WHERE l.type = v.number AND v.type='L' AND (l.type & 256)=256 AND spid IN (SELECT blocked FROM #blk) ORDER BY spid /* delete all blocking spids except blockers */ DELETE FROM #blk WHERE blocked <> 0 /* get each spid from sysprocesses which is referenced in the "blocked" column of #blk. This should be the head of each blocking chain */ SELECT "Blocking Process(es)" SELECT "BLOCKED SPID"=spid, "LOGIN NAME"=SUSER_NAME(suid), "DB NAME"=DB_NAME(dbid), "BLOCKING SPID"=blocked FROM #blk WHERE blocked = 0 /* For each spid at the head of a blocking chain print its input buffer to show what query it's running */ SELECT " Last Command from Blocking Processes" SELECT @spid = (SELECT MIN(spid) FROM #blk) WHILE @spid IS NOT NULL BEGIN SELECT @CMD = 'SELECT "BLOCKED SPID ' + CONVERT(VARCHAR(3),@spid) + '"' + " DBCC INPUTBUFFER(" + CONVERT(VARCHAR(3),@spid) + ") " EXEC (@CMD) SELECT @spid = (SELECT MIN(spid) FROM #blk WHERE spid > @spid) END DROP table #blk GO