Identifying the Complete Session Blocking Chain in SQL Server

Introduction
T-SQL Overview
SQL Query
T-SQL description
Conclusion

Introduction

In the world of SQL Server, dealing with blocking sessions can be a common challenge that affects database performance. To gain insights into this issue, let's explore a SQL query that displays a tree-like structure of the blocking chain, helping to identify the root cause of blocking and its impact on database operations.

T-SQL Overview

This SQL query consists of multiple parts:
  • Temporary Table Creation: The script creates a temporary table #blocks to store information about blocking sessions, including the session ID (spid), the session ID that is being blocked (blocked), and the SQL batch being executed (batch).
  • Recursive Common Table Expression (CTE): The recursive CTE blocking_tree constructs a tree-like structure of the blocking chain by recursively joining rows from the #blocks table. This CTE identifies the blocking sessions and their relationships, organizing them into a hierarchical structure.
  • Final Query: The final query retrieves information about blocking sessions and associated details such as session type, login name, database, SQL text, wait resource, and more. It also formats the output to display the blocking sessions in a tree-like structure, making it easier to visualize the blocking chain.

T-SQL Query

You can use different conditions in the ORDER BY clause to achieve the desired result.

if object_id('tempdb..#blocks') is not null
    drop table #blocks
select
    spid,
    blocked,
    replace (replace (st.text, char(10), ' '), char (13), ' ' ) as batch
into
    #blocks
from
    sys.sysprocesses spr
    cross apply
    sys.dm_exec_sql_text(spr.sql_handle) st
go

with blocking_tree (spid, blocking_spid, [level], batch)
as
(
    select
        blc.spid,
        blc.blocked,
        cast (replicate ('0', 4-len (cast (blc.spid as varchar))) + cast (blc.spid as varchar) as varchar (1000)) as [level],
        blc.batch
    from
        #blocks blc
    where
        (blc.blocked = 0 or blc.blocked = spid)
    and
        exists (select * from #blocks blc2 where blc2.blocked = blc.spid and blc2.blocked <> blc2.spid)
    union all
    select
        blc.spid,
        blc.blocked,
        cast(bt.[level] + right (cast ((1000 + blc.spid) as varchar (100)), 4) as varchar (1000)) as [level],
        blc.batch
    from  
        #blocks as blc
        inner join
        blocking_tree bt
            on blc.blocked = bt.spid
    where
        blc.blocked > 0
    and
        blc.blocked <> blc.spid
)
select
    N'' + isnull(replicate (N'|         ', len (level)/4 - 2),'') + case when (len(level)/4 - 1) = 0 then '' else '|------  ' end + cast (bt.spid as nvarchar (10)) as blocking_tree,
    spr.lastwaittype   AS [type],
    spr.loginame       AS [login_name],
    db_name(spr.dbid)  as [source_database],
    st.text            AS [sql_text],
    case when cur.sql_handle is null then '' else (select [text] from sys.dm_exec_sql_text (cur.sql_handle)) end as [cursor_sql_text],
    db_name(sli.rsc_dbid)  as [database],
    object_schema_name(sli.rsc_objid,sli.rsc_dbid) as [schema],
    object_name(sli.rsc_objid, sli.rsc_dbid) as [table],
    spr.waitresource   as [wait_resource],
    spr.cmd            as [command],
    spr.program_name   as [application],
    spr.hostname       as [hostname],
    spr.last_batch     as [last_batch_time]
from
    blocking_tree bt
    left outer join
    sys.sysprocesses spr
        on spr.spid = bt.spid
    cross apply
    sys.dm_exec_sql_text(spr.sql_handle) st
    left join
    sys.dm_exec_cursors(0) cur
        on cur.session_id = spr.spid
        and cur.fetch_status != 0
    join
    sys.syslockinfo sli
        on sli.req_spid = spr.spid
        and sli.rsc_type = 5
        and object_name(sli.rsc_objid, sli.rsc_dbid) is not null
order by
    level asc;
cached query stats

T-SQL description

Now, let's break down each component and understand its significance

Column              | Description
------------------- | ---------------------------------------------------------
blocking_tree       | Blocking tree structure.
type                | A string indicating the name of the last or current wait type.
login_name          | Login name.
source_database     | Source database.
sql_text            | Last SQL statement.
cursor_sql_text     | SQL text of the batch that declared the cursor.
database            | Database associated to the locked resource.
schema              | Schema associated to the locked resource.
table               | Table associated to the locked resource.
wait_resource       | Textual representation of a lock resource.
command             | Command currently being executed.
application         | Name of the application program.
hostname            | Hostname of the client.
last_batch_time     | Last time a client process executed a statement.

Conclusion

In conclusion, by understanding and analyzing the output of this SQL query, database administrators can gain valuable insights into the blocking sessions occurring in their SQL Server environment. This information is crucial for diagnosing performance issues, identifying bottlenecks, and optimizing database operations for improved efficiency and reliability.


Rate Your Experience

: 89 : 0

Online Tests
Read more

Oracle Database
Read more

MSSQL Database
Read more

PostGres Database
Read more

Linux
Read more

ASP/C#
Read more

Navigation Panel