客户端收到错误 1205,表示这个事务被选成了死锁的牺牲者,并且已经回滚。死锁是两个以上的会话互相等,和 一个会话堵住另一串会话 不是同一种等待。默认的 system_health 扩展事件里有 xml_deadlock_report,不必先开跟踪标志 1222。
在出问题的实例上执行。文件目标里还留着的死锁图:
1 | SELECT CAST(event_data AS XML) AS deadlock_graph |
system_health*.xel 相对 SQL Server 的日志目录。结果按文件里的顺序往后是更新的。环缓冲和文件都会滚动,早于保留窗口的图查不到。点开 XML,看两处:
victim-list里的victimProcess id,这是被回滚的那个process-list里每个process的spid、loginname、clientapp、hostname,以及下面的inputbuf
inputbuf 是这个会话当时提交的语句。两个进程各自持有对方要的锁,图里的 resource-list 能看到锁的对象。牺牲者通常是 SQL Server 认为回滚成本较低的那个,不一定是「写错」的那个。
应用侧如果会重试 1205,重试必须是整段事务再跑一遍。只重试失败的那一条语句,事务已经回滚,前面的修改也不在了。
同一时间如果只是许多人等同一个锁、没有 1205,用阻塞那篇的 blocking_session_id。死锁图是空的,就说明这次不是死锁,或者图已经被滚掉了。