0%

SQL Server 死锁 1205,从 system_health 把图取出来

客户端收到错误 1205,表示这个事务被选成了死锁的牺牲者,并且已经回滚。死锁是两个以上的会话互相等,和 一个会话堵住另一串会话 不是同一种等待。默认的 system_health 扩展事件里有 xml_deadlock_report,不必先开跟踪标志 1222。

在出问题的实例上执行。文件目标里还留着的死锁图:

1
2
3
SELECT CAST(event_data AS XML) AS deadlock_graph
FROM sys.fn_xe_file_target_read_file(N'system_health*.xel', NULL, NULL, NULL)
WHERE object_name = N'xml_deadlock_report';

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。死锁图是空的,就说明这次不是死锁,或者图已经被滚掉了。