SQL Find Blocking Generator — SQL Server Blocking Analysis

Generate T-SQL queries that diagnose SQL Server blocking in seconds. See which sessions are blocked, which sessions are causing the blocking, how long the wait has been, and the exact SQL each session is running. Three patterns: standard report, full blocking chain, and summary by head blocker.

SQL Server / Azure SQL
📚 Guide & Tutorial: Finding and Resolving Blocking Queries in SQL Server — step-by-step walkthrough with examples.

Examples

Example: Standard blocking query — see who is blocking whom

Shows all blocked sessions, what they are waiting for, and the SQL text of both the blocked and blocking session.

SELECT
    r.session_id                          AS blocked_session,
    r.blocking_session_id                 AS blocking_session,
    r.wait_type,
    r.wait_time / 1000.0                  AS wait_seconds,
    r.status,
    DB_NAME(r.database_id)                AS database_name,
    SUBSTRING(bt.text, (r.statement_start_offset/2)+1,
        ((CASE r.statement_end_offset
            WHEN -1 THEN DATALENGTH(bt.text)
            ELSE r.statement_end_offset END
         - r.statement_start_offset)/2)+1) AS blocked_sql,
    SUBSTRING(bk.text, 1, 500)            AS blocking_sql
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle)  AS bt
LEFT JOIN sys.dm_exec_requests blk
    ON blk.session_id = r.blocking_session_id
OUTER APPLY sys.dm_exec_sql_text(blk.sql_handle) AS bk
WHERE r.blocking_session_id > 0
  AND r.wait_time > 5000  -- 5 seconds
ORDER BY r.wait_time DESC;

The blocking_sql column shows the SQL text the head blocker is currently running. This is the query holding the lock.

Example: Head blocker identification — full blocking chain

Identifies the root head blocker using a recursive CTE. Useful when there are chains: A blocks B, B blocks C.

WITH BlockingChain AS (
    SELECT
        session_id,
        blocking_session_id,
        wait_time,
        CAST(session_id AS VARCHAR(MAX)) AS chain
    FROM sys.dm_exec_requests
    WHERE blocking_session_id > 0
    UNION ALL
    SELECT
        r.session_id,
        r.blocking_session_id,
        r.wait_time,
        bc.chain + ' → ' + CAST(r.session_id AS VARCHAR(10))
    FROM sys.dm_exec_requests r
    JOIN BlockingChain bc ON r.session_id = bc.blocking_session_id
)
SELECT DISTINCT
    blocking_session_id AS head_blocker,
    COUNT(*) OVER (PARTITION BY blocking_session_id) AS sessions_blocked,
    MAX(wait_time) OVER (PARTITION BY blocking_session_id) / 1000.0 AS max_wait_seconds
FROM BlockingChain
ORDER BY sessions_blocked DESC
OPTION (MAXRECURSION 20);

What This Tool Does

The Find Blocking Generator produces T-SQL queries that query SQL Server's dynamic management views (DMVs) to identify blocking sessions — sessions that are holding locks preventing other sessions from proceeding. The generated query shows the blocked session, the blocking session, wait time, wait type, database, and the SQL text of both sessions.

Three patterns are available: a standard blocking report, a recursive blocking chain query that identifies the root head blocker in multi-level chains, and a summary that counts how many sessions each head blocker is holding up.

How to Use It

Understanding the Output Columns

ColumnMeaningWhat to look for
blocked_sessionSession being blockedThe victim — the query that cannot proceed
blocking_sessionSession holding the lockThe cause — investigate this session first
wait_typeType of lock being waited onLCK_M_X = exclusive lock, LCK_M_S = shared lock
wait_secondsHow long the block has lastedAnything over 30s is worth investigating
blocked_sqlSQL the blocked session is runningThe query that is stuck waiting
blocking_sqlSQL the blocker is runningThe query holding the lock — this is usually the root cause

How to Resolve Blocking

Once you identify the head blocker:

Privacy & Security

All SQL generation runs in your browser. No server names, query text, or diagnostic data is transmitted anywhere. The generated queries read from DMVs only — they do not modify any data. Viewing DMVs requires VIEW SERVER STATE permission.

Common Problems & Fixes

ProblemCauseFix
No rows returned but users report slow queriesWait time filter too high, or blocking resolvedLower the minimum wait time to 1 second; run during the incident
Permission denied on sys.dm_exec_requestsUser lacks VIEW SERVER STATE permissionGRANT VIEW SERVER STATE TO [login]; requires sysadmin
blocking_sql is NULLBlocking session is idle — transaction is open but no active queryThe session has an open uncommitted transaction with no current SQL. Check sys.dm_exec_sessions for last_request_start_time.
Chain query hits MAXRECURSION limitBlocking chain deeper than 20 levelsIncrease OPTION (MAXRECURSION N) — deep chains usually indicate a systemic problem

💡 Blocking is often caused by long-running queries that hold locks. Use the SQL Formatter to make the blocking SQL readable before analyzing it. If the blocking query involves a PIVOT or complex aggregation, the PIVOT Generator can help you rebuild a more efficient version. For recurring blocking on queries that scan large date ranges, a Date Spine with indexed joins often resolves the issue.

SQL Server Admin Toolkit

Blocking analysis is one of several SQL Server admin tasks:

Frequently Asked Questions

What is SQL Server blocking?
Blocking occurs when one session holds a lock on a resource and another session needs a lock on the same resource. The second session waits until the first releases its lock. Prolonged blocking causes timeouts and performance degradation.
What is the difference between blocking and deadlock?
Blocking is a wait — one session waits for another to release a lock. Deadlock is a circular wait — session A waits for session B, and session B waits for session A. SQL Server resolves deadlocks automatically by killing one session; blocking must be resolved manually or by query timeout.
Which DMVs are used to find blocking?
The primary DMV is sys.dm_exec_requests (active requests). It is joined to sys.dm_exec_sessions (session details), sys.dm_exec_sql_text (SQL text), and sys.dm_os_waiting_tasks (wait info) to build a complete blocking picture.
How do I kill a blocking session?
Once you identify the head blocker's session_id from the query output, run: KILL session_id; Only kill sessions you are certain are safe to terminate. Always investigate the root cause rather than repeatedly killing sessions.
Can I schedule this query to run automatically?
Yes. Wrap the generated query in a SQL Server Agent job that captures the output to a table. This creates a blocking history log useful for diagnosing recurring issues.

Related SQL Tools