第十六章——处理锁、阻塞和死锁(3)——使用SQLServer Profiler侦测死锁
前言:
作为DBA,可能经常会遇到有同事或者客户反映经常发生死锁,影响了系统的使用。此时,你需要尽快侦测和处理这类问题。
死锁是当两个或者以上的事务互相阻塞引起的。在这种情况下两个事务会无限期地等待对方释放资源以便操作。下面是死锁的示意图:
本文将使用SQLServer Profiler来跟踪死锁。
准备工作:
为了侦测死锁,我们需要先模拟死锁。本例将使用两个不同的会话创建两个事务。
步骤:
1、 打开SQLServer Profiler
2、 选择【新建跟踪】,连到实例。
3、 然后选择【空白】模版:
4、 在【事件选择】页中,展开Locks事件,并选择以下事件:
1、 Deadlock graph
2、 Lock:Deadlock
3、 Lock:Deadlock Chain
5、 然后打开TSQL事件,并选择以下事件:
1、 SQL:StmtCompleted
2、 SQL:StmtStarting
6、 点击【列筛选器】,在跟踪属性中,选择数据库名为需要侦测的数据库,这里使用AdventureWorks。
7、 在【组织列】中,调整顺序,如下:
8、 点击运行。
9、 然后打开SQLServer,并打开两个连接。
10、 在第一个窗口中输入并执行下面脚本:
15、切换到SQLServer Profiler,可以看到下面的截图:
16、 点击【Deadlock graph】时间,会显示死锁的图像:
17、可以保存死锁图像,右键然后选择导出事件数据,并另存为xdl文件:
下面是其XML格式:
分析:
在本文中,首先创建一个Profiler空白模版,然后选择下面的事件进行监控:
1、 Deadlock graph
2、 Lock:Deadlock
3、 Lock:Deadlock Chain
4、 SQL:StmtCompleted
5、 SQL:StmtStarting
然后通过限定数据库,来限制监控过得对象范围。
在配置好之后,运行跟踪,并在ssms中运行脚本。SQLServer会自动处理和侦测这种类型的死锁。然后会在第二个窗体中收到1205的错误。
在SQLServer Profiler中,演示了如何收集死锁事件,在跟踪结果中可以看到两个事务尝试在一个拥有共享锁的键上添加排它锁。通过死锁图像,可以看到死锁发生的细节。
为了避免或者最小化死锁的发生,有一些建议可以参考:
1、 确保你的事务尽可能地小,这里指范围。
2、 使用较低隔离级别的事务。
3、 对于可能的查询,使用NOLOCK查询提示。
4、 规范化数据库设计。
5、 在需要的列上创建索引,以便是表不需要经常扫描,减少锁问题的发生。
6、 控制数据库对象访问的顺序是相同的顺序。
- 2楼yaojie8610昨天 14:50
- 很有用的工具,非常感谢。n其实我们之前都有使用这个工具的,但都是自己摸索。所以想请假下是否有资料详细介绍这个工具的,最好能清楚的了解每个events的作用。谢谢!
- Re: DBA_Huangzj昨天 15:00
- 回复yaojie8610n事件的类型几百种,很难说清楚,而且常规使用也就那些,所以没必要过于在意其他,常规使用的那些事件,网上多多少少都有说明
- Re: yaojie8610昨天 15:20
- 回复DBA_Huangzjn谢谢。n如果是我想监控sql服务器上面究竟是哪些脚本操作最耗费资源。n之前都只是监控BatchCompleted。监控结果里面我们通常拿“运行时间”作为标准去进行比较。在这里CPU时间是否起作用呢?不知道这种做法是否有误?n不好意思,确实很想了解下这个东西,网上详细分析的资料也难找到,麻烦了。
- 1楼DBA_Huangzj昨天 14:06
- [quote=yaojie8610]回复DBA_Huangzjn谢谢。n如果是我想监控sql服务器上面究竟是哪...[/quote]n耗资源主要看的是CPU、reads、write和duration这4个。但是通常的系统不仅仅只有脚本,也有存储过程,所以只是监控BatchCompleted是不够的。在选择大事件的那里可以看到有T-SQL和stored procedure,里面的你可以参考一下,我会陆续发文,有时间可以留意一下
- Re: yaojie8610昨天 14:16
- 回复DBA_Huangzjn谢谢!