SQL数据库锁冲突检测的核心是通过等待图识别循环等待关系,其中节点为事务、边表示“T1→T2”即T1等待T2,死锁当且仅当图中存在有向环;实时构建于锁请求/释放时,环检测常用DFS或Floyd-Warshall变种。

SQL数据库锁冲突检测的核心是识别事务之间因资源竞争形成的循环等待关系,而等待图(Wait-for Graph)正是刻画这种关系的有向图模型。
等待图的节点与边定义
图中每个节点代表一个正在运行的事务(如 T1、T2、T3);若事务 T1 正在等待被事务 T2 持有的锁(例如 T1 请求某行的 X 锁,但该行已被 T2 加了 X 锁且尚未释放),则添加一条有向边 T1 → T2。该边表示“T1 等待 T2”。
注意:边的方向不是“谁阻塞谁”,而是“谁在等谁”——这是构建和判断死锁的关键,容易弄反。
实时构建等待图的触发时机
数据库通常在以下时刻动态更新等待图:
- 事务发起锁请求且无法立即满足(进入锁等待队列)时,检查持有者并插入新边;
- 事务释放锁时,遍历所有等待该资源的事务,移除对应出边,并尝试唤醒可满足的等待者;
- 定时轮询或由锁管理器主动触发图快照,用于周期性死锁检测。
从等待图识别锁冲突与死锁
锁冲突不等于死锁,但死锁必然表现为等待图中存在有向环:
- 单边等待(T1 → T2):只是阻塞,非死锁;
- 环形等待(T1 → T2 → T3 → T1):典型死锁,所有事务相互等待,无法自行推进;
- 长链等待(T1 → T2 → T3 → T4):若 T4 不等待 T1,则无环,系统仍可推进,不算死锁。
主流数据库(如 SQL Server、PostgreSQL)均基于此逻辑实现死锁检测器:定期遍历等待图做环检测(常用深度优先搜索或 Floyd-Warshall 变种)。
实际监控中的常见误区
运维中看到“锁等待”不等于存在死锁,需结合图结构判断:
- sys.dm_tran_locks + sys.dm_exec_requests 可查当前持锁与等锁事务,但需人工拼接等待链;
- SQL Server 的 trace flag 1222 或扩展事件 xml_deadlock_report 输出的是已发生的死锁图(Deadlock Graph),本质是等待图的环子图;
- 高并发下短暂等待(毫秒级)可能快速消解,等待图不断变化,仅快照不足以反映瞬态冲突,需配合等待时间阈值(如 wait_time > 5000ms)辅助判定严重阻塞。
理解等待图的构建逻辑,才能准确解读数据库日志、监控指标和告警信息,避免将正常锁等待误判为死锁故障。










