出现死锁怎么查与避免
死锁的识别(错误 1205 类)、从日志定位死锁图、理解胜出/牺牲机制,以及应用侧避免死锁的常见手法。
简短答案
死锁时引擎选一个会话做「牺牲品」回滚,报 1205 类错误,其余会话继续。死锁不是引擎故障,而是并发事务互相等锁。要「查出来 + 降概率」,而不是追求「不出现」。
排查步骤
- 开死锁图(需管理员权限,以版本支持为准):
EXEC sp_lock @spid = -1; -- 当前锁快照
DBCC SQLDEBUG (DEADLOCKTRACEON); -- 记录死锁图
更常用:在 SSMS 错误日志中检索死锁图,查看两个会话分别持有的锁与等待的锁。
- 定位涉及的事务:看死锁图里的 SQL 文本,确认两个事务访问对象与顺序。
- 应用侧避免手法:
- 固定访问顺序(所有事务按同一顺序访问多行/多表);
- 缩短事务,别在大事务里夹杂耗时代码;
- 用乐观并发控制或合理隔离级别(如行级锁 + 快照隔离,视版本支持)。
- 被牺牲的事务在应用层做重试(捕获 1205 类错误后有限重试)。
- 各版本并发特性以 SQL Server 2022 Developer 条目页核对。
现象对照表
| 现象 | 含义 |
|---|---|
| 偶尔一个会话报 1205 | 死锁牺牲品,正常并发现象 |
| 高频反复出现 | 访问顺序/事务设计有问题,需整改 |
操作小结
- 先定位死锁图,看清两个事务的锁持有与等待。
- 固定访问顺序 + 缩短事务,是降低死锁概率的主力。
- 应用层对 1205 做有限重试兜底。