Find lead blocker on a SQL Server Instance

Post image for Find lead blocker on a SQL Server Instance

by Tarun Kumar Jaiswal on December 26, 2011

When database server is experiencing slowness one of the very first things we check are blocks. Blocking can be described as

Blocking is an unavoidable characteristic of any relational database management system (RDBMS) with lock-based concurrency. On SQL Server, blocking occurs when one SPID holds a lock on a specific resource and a second SPID attempts to acquire a conflicting lock type on the same resource. Typically, the time frame for which the first SPID locks the resource is very small. When it releases the lock, the second connection is free to acquire its own lock on the resource and continue processing. This is normal behavior and may happen many times throughout the course of a day with no noticeable effect on system performance. – MSDN

When such blocking persists for a longer duration and there are many another SPID waiting directly or indirectly or the lock to be released - one finds many blocks on the server. This degrades performance by causing waits. The first step is to verify what is causing the blocks.

We can use sp_who2 active, sys.dm_exec_requests , sysprocesses or sp_lock to get information about the locks. When there are large number of blocks on a server and one needs to figure out what is the root SPID that is causing all this – We are looking for a lead blocker. Finding lead blocker in a chain of blocks is tedious process. Which is why I normally use below two scripts to get the required data :-


select  a.spid, a.blocked, b.spid, b.blocked

from sysprocesses a inner join sysprocesses b

on
b.spid= a.blocked and b.blocked = 0 and a.spid<> a.blocked

Once you have the lead blocker SPID , you can see the statement using DBCC INPUTBUFFER (SPID) or use the below script to get the SQL Text of lead blocker in a single go.


SELECT

    spid 

    ,sp.status 

    ,loginame   = SUBSTRING(loginame, 1, 12) 

    ,hostname   = SUBSTRING(hostname, 1, 12) 

    ,blk        = CONVERT(char(3), blocked) 

    ,open_tran 

    ,dbname     = SUBSTRING(DB_NAME(sp.dbid),1,10) 

    ,cmd 

    ,waittype 

    ,waittime 

    ,last_batch 

    ,SQLStatement       = 

        SUBSTRING

        ( 

            qt.text, 

            er.statement_start_offset/2, 

            (CASE WHEN er.statement_end_offset = -1 

                THEN LEN(CONVERT(nvarchar(MAX), qt.text)) * 2 

                ELSE er.statement_end_offset 

                END - er.statement_start_offset)/2 

        ) 

FROM master.dbo.sysprocesses sp 

LEFT JOIN sys.dm_exec_requests er 

    ON er.session_id = sp.spid 

OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) as qt 

WHERE spid IN (SELECT blocked FROM master.dbo.sysprocesses) 

AND blocked = 0

 

There is a very good article on Microsoft Support portal regarding How to monitor blocking in SQL Server 2005 and in SQL Server 2000

  • Anon

    This is Kalen Delaney’s code. Give credit where it is due.

Previous post:

Next post: