查 sys.dm_exec_requests 是SQL Server锁等待排查最直接入口,通过blocking_session_id、wait_type、wait_time等字段定位阻塞链,需结合sys.dm_tran_locks、DBCC INPUTBUFFER及事务视图综合分析。

查 sys.dm_exec_requests 看当前阻塞链
SQL Server 里锁等待最直接的入口就是这个动态管理视图,它能告诉你谁在等、等谁、等了多久、执行什么语句。关键字段:blocking_session_id(非零说明被阻塞),wait_type(如 LCK_M_U、LCK_M_S 表示更新/共享锁等待),wait_time(毫秒级,>0 就真卡着了)。
实操建议:
- 优先过滤
status = 'suspended'或wait_type LIKE 'LCK%'的行,排除空闲或 CPU 等待 -
session_id和blocking_session_id要一起查,避免只看等待方漏掉根因会话 - 别只依赖
command字段——它可能截断,真正语句得用sys.dm_exec_sql_text(拿完整文本sql_handle) - 如果
blocking_session_id = 0但wait_type是锁类型,可能是自己锁自己(比如未提交事务里重复更新同一行)
连查 sys.dm_tran_locks 定位具体资源冲突
sys.dm_exec_requests 告诉你“谁卡住了”,sys.dm_tran_locks 才告诉你“卡在哪条记录/哪个页/哪张表”。重点看 resource_type(如 OBJECT、PAGE、KEY)、resource_description(比如 database_id:5 object_id:123456789 page_id:1234),再结合 request_mode(S 共享,X 排他)判断兼容性。
实操建议:
- 把
sys.dm_tran_locks和sys.dm_exec_requests按request_session_id关联,才能把“等待会话”和“它想拿的锁资源”对应上 -
resource_description里如果是KEY类型,通常带一个哈希值(如(8194443284a0)),没法直接反查行数据,但能确认是行级锁争用 - 注意
request_status:不是所有锁都是GRANT状态,WAIT才是真卡住;CONVERT表示正在升级锁(比如从U升到X),也可能卡住
用 DBCC INPUTBUFFER(session_id) 看阻塞源头语句
session_id)有时候 sys.dm_exec_requests 里查不到完整 SQL,或者会话已断开但锁还挂着,DBCC INPUTBUFFER 就是兜底方案——它读的是会话最后一次发来的完整命令缓冲区,哪怕语句执行完了、连接断了,只要事务没提交,缓冲区内容还在(有一定时效性,但比啥都没有强)。
实操建议:
- 必须传真实
session_id,不能传blocking_session_id——后者可能已结束,DBCC INPUTBUFFER会报错 - 结果里的
EventInfo列就是原始语句,注意检查是否有隐式事务(比如没写BEGIN TRAN但开了SET IMPLICIT_TRANSACTIONS ON) - 如果返回空或只有
COMMIT/ROLLBACK,说明阻塞源语句早就执行完,但事务没关,得顺藤摸瓜找前面的BEGIN TRAN
警惕 tempdb 争用和未提交事务残留
很多锁等待看着像业务表冲突,其实是 tempdb 里排序、哈希、临时表引发的 ALLOC_UNIT 或 PAGE 锁;还有更隐蔽的:应用层异常中断后,连接断了但事务没回滚,锁一直占着,session_id 在 sys.dm_exec_sessions 里都查不到,只能靠 sys.dm_tran_active_transactions + sys.dm_tran_database_transactions 联查。
实操建议:
- 查
sys.dm_db_task_space_usage看哪些会话在tempdb分配最多空间,配合session_id反推源头 - 运行
SELECT * FROM sys.dm_tran_active_transactions WHERE transaction_state = 2(active 状态),再关联sys.dm_tran_database_transactions看是否挂在某个数据库上 - 不要只盯着
sys.dm_exec_requests里status = 'running'的会话——真正的问题往往藏在sleeping但open_transaction_count > 0的连接里
锁等待排查最难的不是找语句,而是确认“谁该为这个未提交事务负责”。应用日志、SQL Server Agent 作业历史、甚至网络抓包,有时比 DMV 更快定位到那个忘了加 COMMIT 的存储过程调用点。










