如何在SQL Server中排查一周前的死锁及引发进程?
查找SQL Server上周死锁进程的方法及死锁问题处理
没问题,我来帮你解决SQL Server死锁查询和作业报错的问题!
一、找回上周死锁记录的核心方法
你提到Extended Events只保留昨晚的数据,那优先试试系统健康会话(System Health Session)——这是SQL Server默认开启的扩展事件会话,会自动收集死锁、内存压力等关键信息,默认保留时间比普通自定义会话久很多。
系统健康会话死锁查询脚本
直接运行下面的脚本,就能筛选出上周的死锁记录,还能拿到可视化的死锁图:
SELECT -- 提取死锁XML图,可复制到SSMS中查看可视化视图 XEvent.query('(event/data/value/deadlock)[1]') AS DeadlockGraph, -- 死锁发生的时间 XEvent.value('(event/@timestamp)[1]', 'datetime') AS DeadlockTime FROM ( -- 读取系统健康会话的日志文件 SELECT CAST(event_data AS XML) AS XEvent FROM sys.fn_xe_file_target_read_file( N'system_health*.xel', -- 匹配系统健康会话的日志文件 NULL, NULL, NULL ) -- 只筛选死锁报告事件 WHERE object_name = 'xml_deadlock_report' ) AS DeadlockEvents -- 过滤出上周的记录 WHERE DeadlockTime >= DATEADD(week, -1, GETDATE()) -- 按时间倒序,最新的死锁排前面 ORDER BY DeadlockTime DESC;
小提示:把
DeadlockGraph列的XML内容复制到SSMS的“XML编辑器”里,就能看到直观的死锁流程图,清楚看到两个冲突进程的执行语句、锁资源、等待关系。
二、如果系统健康会话也没保留上周数据怎么办?
如果系统健康会话的日志也被覆盖了,那可以从这两个方向补全历史监控:
- 启用死锁跟踪标志:开启
1222和1204跟踪标志,SQL Server会把死锁信息写入错误日志(1222是XML格式,1204是文本格式)。全局开启的话运行:
要是想重启后依然生效,得在SQL Server启动参数里添加DBCC TRACEON(1222, 1204, -1);-T1222 -T1204。 - 调整扩展事件保留策略:自定义死锁监控会话时,设置更大的文件大小和更多的滚动文件数,比如:
CREATE EVENT SESSION [Deadlock_Monitor] ON SERVER ADD EVENT sqlserver.xml_deadlock_report ADD TARGET package0.event_file( SET filename=N'Deadlock_Monitor.xel', max_file_size=(100), -- 单个文件最大100MB max_rollover_files=(10) -- 保留10个滚动文件 ) WITH (STARTUP_STATE=ON); -- 启动时自动运行
三、针对作业死锁报错的处理建议
你的作业报错显示进程被选为死锁牺牲品,除了查死锁根源,还可以这么优化:
- 分析死锁根源:用上面的脚本找到对应时间的死锁图,看两个冲突进程的SQL语句、锁的资源(比如表、索引、键值),找到冲突点——比如是不是两个作业同时修改同一张表的同一批数据,或者其中一个作业的查询没加索引导致锁范围过大。
- 优化查询与事务:给慢查询加合适的索引,减少锁的持有时间;拆分大事务成多个小事务,缩短锁占用时长;开启
READ COMMITTED SNAPSHOT ISOLATION(RCSI),用行版本控制替代阻塞式读。 - 调整死锁优先级:如果这个作业是核心业务,可在作业的事务开头加
SET DEADLOCK_PRIORITY HIGH;,降低它被选为牺牲品的概率(但这只是缓解,不是根本解决方法)。 - 添加重试逻辑:在作业代码里捕获死锁异常(错误号
1205),间隔几秒后重试2-3次,避免单次死锁就导致作业失败。
内容的提问来源于stack exchange,提问作者hassan.h
相关产品推荐
相关产品推荐

