下的Lock:Deadlock和Deadlock graph即可,trace文件大小设置为100M上限以便分析
2)一段时间后停止抓取,很直观看到死锁一直出现,且点开所有deadlock graph得到死锁图形分析,死锁都是发生在同一资源上:


到这一步为止我们只是能确认死锁发生了,而且发生在同一资源上,还没能获取具体的死锁语句和资源信息,问题还不能得到根本解决。 3)为了查看死锁信息,数据库引擎提供了监视工具:跟踪标识(1222)。打开这个跟踪开关,所有获取的死锁信息会写到SQL Server的错误日志中供我们进一步分析。这一步打开这个开关,在SSMS中运行 DBCC TRACEON(1222,-1); 4)从trace的死锁图形看死锁发生很频繁,为了不让日志增长过大,过2至3分钟后将开关关掉。在SSMS中运行 DBCC TRACEOFF(1222,-1),这一步很重要; 5)打开SQL Server errorlog,找到死锁输出信息,这个输出内容很丰富而且比较复杂,这里只把我们所需的几个重要点挑出来

死锁信息始于 deadlock-list关键字(倒着看),deadlock victim显示死锁的牺牲方,process id显示进程id号,由于截图没那么齐全,还包含很多死锁信息,比如可以查看进程spid号,事务隔离级别,当前正进行的批处理操作,当前正在运行的语句,申请中的资源等等。 通过对错误日志的分析得到死锁批处理和死锁语句:exec usp_obal_import_so,查到死锁语句:delete from t_po_detail where po_number in(select po_number from t_so_po where so_number=@v_vchSOID and whid=@v_vchWHID) and whid=@v_vchWHID,这是usp_obal_import_so中的一段语句,锁资源:表tbl_po_detail_generic(用户脚本定时执行获得) ,但是这个sp的执行根本不会操作tbl_po_detail_generic ,是不是哪里出问题了呢? 6)我们可以在SSMS中看看这条语句的执行计划,运行语句之前在SSMS中运行 set statistics profile on或者在“查询”子菜单中选择“包括实际的执行计划”,我们用第二种更直观,如下

很明显在执行计划中可以看到tbl_po_detail_generic有个全表扫描操作,再与t_po_detail表做hash连接。全表扫描导致每次语句执行会获取该表的表锁,深究原因发现tbl_po_detail_generic的外键约束导致每次删除t_po_detail数据会操作tbl_po_detail_generic表。 7)到这里剖析死锁工作基本结束,后面解决方法有两种:一是根据执行计划在tbl_po_detail_generic建立适当索引避免表扫描;二是如果业务逻辑许可,删掉外键约束。 总结: 要真正做到从源头上降低死锁发生几率,还是要从程式本身做好。如果不能去修改程式,可以考虑从另外几个方面消除死锁:
1 调整索引来调整执行计划,减少锁的申请数目;
2 使用‘nolock‘参数,让SELECT语句不要申请S锁,减少锁申请数目
3 升级锁粒度,将死锁转化成阻塞问题
4 使用快照隔离级别SNAPSHOT LEVEL
SQL Server死锁排查经历 -基于SqlProfiler
标签:建立 ror 解决方法 公司 ref 外键 新建 width 频繁