select t.session_id as waiting_session_id,
db_name(l.resource_database_id),
t.wait_duration_ms/60 as duration_in_seconds,
t.waiting_task_address,
l.request_mode,
l.resource_type,
l.resource_associated_entity_id,
l.resource_description lock_resource_desc,
t.wait_type,
t.blocking_session_id,
t.resource_description as blocking_resource_desc
from sys.dm_os_waiting_tasks t join sys.dm_tran_locks l
on t.resource_address = l.lock_owner_address
where t.session_id > 50
而后分别用不同会话运行以下语句:
会话1:
begin tran
select * from t1;
update t1 set name = 'DDDDDD' where id = 1
会话2:
alter table t1 add col2 varchar(100)
可以使用以上的sys.dm_os_waiting_tasks与sys.dm_tran_locks相关的语句,查询到对应的信息:

一般来说,解决阻塞问题主要有以下几个方案:
1. 杀掉会话
2. 让SQLServer的事务尽量短小
3. 事务应当持有的锁的数量应当最小化
4. 如果是读写阻塞可以考虑使用读写分离或者业务能容忍的话使用read uncommitted隔离级别
-- 监控脚本:查询当前访问 SQL Server 2017 的客户端及其执行的 SQL 语句
-- 作者:Grok
-- 日期:2025-08-31
-- 说明:此脚本使用动态管理视图(DMV)实时监控用户会话(排除系统会话 session_id <= 50)。
-- 输出包括客户端 IP、主机名、程序名、登录名、会话状态、当前执行的 SQL 语句等。
-- 建议:作为 SQL Agent Job 定期运行,或在 SSMS 中手动执行。
-- 权限要求:需要 VIEW SERVER STATE 权限。
SELECT
s.session_id AS [Session ID], -- 会话 ID
c.client_net_address AS [Client IP], -- 客户端 IP 地址
s.host_name AS [Host Name], -- 客户端主机名
s.program_name AS [Program Name], -- 连接程序名(如 'Microsoft SQL Server Management Studio' 或应用名)
s.login_name AS [Login Name], -- 登录用户名
s.status AS [Session Status], -- 会话状态(running, sleeping, suspended 等)
r.blocking_session_id AS [Blocking Session ID],-- 如果被阻塞,显示阻塞会话 ID(0 表示无阻塞)
r.wait_type AS [Wait Type], -- 等待类型(如果在等待,如 LCK_M_S 表示锁等待)
r.wait_time AS [Wait Time (ms)], -- 等待时间(毫秒)
DB_NAME(r.database_id) AS [Database Name], -- 当前数据库名
r.command AS [Command Type], -- 命令类型(如 SELECT, UPDATE)
SUBSTRING(t.text, (r.statement_start_offset/2) + 1,
((CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(t.text)
ELSE r.statement_end_offset END
- r.statement_start_offset)/2) + 1) AS [Executing SQL Statement], -- 当前执行的 SQL 语句片段
t.text AS [Full Batch Text], -- 完整批处理 SQL 文本
r.start_time AS [Request Start Time], -- 请求开始时间
r.cpu_time AS [CPU Time (ms)], -- 已使用 CPU 时间(毫秒)
r.total_elapsed_time AS [Elapsed Time (ms)], -- 总执行时间(毫秒)
r.reads AS [Physical Reads], -- 物理读次数
r.writes AS [Writes], -- 写次数
r.logical_reads AS [Logical Reads] -- 逻辑读次数
FROM
sys.dm_exec_sessions s
LEFT JOIN
sys.dm_exec_requests r ON s.session_id = r.session_id
LEFT JOIN
sys.dm_exec_connections c ON s.session_id = c.session_id
OUTER APPLY
sys.dm_exec_sql_text(r.sql_handle) t -- 获取 SQL 文本
WHERE
s.session_id > 50 -- 排除系统会话,只监控用户会话
AND s.is_user_process = 1 -- 只包括用户进程
ORDER BY
r.total_elapsed_time DESC, -- 按执行时间降序排序,突出慢查询
s.session_id; -- 其次按会话 ID 排序
-- 使用说明:
-- 1. 在 SSMS 中运行此查询,即可实时查看客户端和 SQL 语句。
-- 2. 如果需要自动化监控,可创建 SQL Agent Job,每 1-5 分钟运行,并将结果插入日志表:
-- CREATE TABLE MonitoringLog (LogTime DATETIME, SessionID INT, ClientIP VARCHAR(50), SQLText NVARCHAR(MAX), ...);
-- INSERT INTO MonitoringLog SELECT GETDATE(), session_id, client_net_address, text, ... FROM ...;
-- 3. 如果有阻塞,关注 Blocking Session ID > 0 的行,进一步调查阻塞链。
-- 4. 性能提示:此查询开销低,但高峰期频繁运行可能略增负载;限制 TOP 100 以优化。
-- 5. 扩展:结合 Extended Events 捕获历史数据:
-- CREATE EVENT SESSION [SessionMonitor] ON SERVER
-- ADD EVENT sqlserver.sql_statement_completed( WHERE session_id > 50 );
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8520577/viewspace-2920331/ ,如需转载,请注明出处,否则将追究法律责任。