sql server锁监控与死锁排查需坚持“早发现、准定位、快干预”,通过sys.dm_exec_requests和sys.dm_tran_locks实时监控阻塞与锁持有,结合死锁图分析resource-list和inputbuf定位冲突点,识别未按序访问表、长事务、缺失索引等高风险模式,并用kill或隔离级别调整快速缓解,修复后须压测验证。

SQL 数据库锁监控与死锁排查,核心在于“早发现、准定位、快干预”。重点不是等报错才行动,而是通过系统视图、等待链分析和事务行为观察,把锁升级、阻塞蔓延和循环等待扼杀在初期。
实时监控阻塞与锁持有情况
SQL Server 中最直接的方式是查询 sys.dm_exec_requests 和 sys.dm_tran_locks。前者看哪些会话正在等待(wait_type 不为 NULL),后者看谁持有哪些资源锁(如 KEY、PAGE、OBJECT)。组合查询可快速识别“谁被谁堵住”:
- 用 blocking_session_id > 0 筛出被阻塞的请求,再关联 session_id 找到阻塞源头
- 查 sys.dm_tran_locks 时加上 resource_description 和 request_mode,能看清是 S 锁还是 X 锁、锁在哪个索引键上
- 配合 sys.dm_exec_sessions 获取 login_name、host_name、program_name,便于联系业务方确认操作意图
捕获并分析死锁图(Deadlock Graph)
死锁发生后,SQL Server 默认会记录 XML 格式的死锁图(需开启跟踪标志 1222 或使用 Extended Events)。关键信息藏在图中两个 process 节点里:
- 每个 process 的 inputbuf 显示触发死锁的 SQL 语句(注意:可能是批处理中的一段,不一定是完整存储过程)
- executionStack 可定位具体执行到哪一行(尤其对嵌套调用有用)
- 对比两个 process 的 resource-list,找出它们互相等待的同一资源(比如同一个聚集索引键),这就是死锁环的闭合点
推荐用 Extended Events 创建 xml_deadlock_report 事件会话,比 SQL Trace 更轻量、更稳定。
识别高风险事务模式
很多死锁不是偶然,而是由固定写法诱发。重点关注以下场景:
- 未按固定顺序访问多张表:例如 A 过程先更新 users 再更新 orders,B 过程反过来,极易形成循环等待
- 长事务 + 高频更新:显式 BEGIN TRAN 后执行大量逻辑或等待外部响应(如 HTTP 调用),导致锁长时间持有
- 缺失索引导致锁升级:UPDATE WHERE name = 'xxx' 没走索引,引发全表扫描和大量行锁,最终升级为表锁,扩大冲突面
- 使用 NOLOCK(READ UNCOMMITTED)读取后又做 UPDATE:看似不加锁读,但后续写仍需加锁,且因读取逻辑混乱,可能让应用做出错误判断,间接引发竞争
快速缓解与验证修复效果
线上出现严重阻塞或死锁时,优先保障业务可用:
- 用 KILL [session_id] 终止已明确无业务价值的阻塞源头(务必先查 sys.dm_exec_sql_text 确认当前语句)
- 若死锁高频复现,临时降低隔离级别(如 READ COMMITTED SNAPSHOT)可大幅减少锁争用,但需评估 tempdb 压力和版本存储开销
- 修复后,用相同数据+并发压测验证:模拟两路请求按原路径执行,确认不再出现死锁图或长时间阻塞
不复杂但容易忽略:多数死锁问题,改一两条 SQL 的访问顺序或加一个覆盖索引就能解决,不必动架构。










