SQL Server中如何监控死锁(Deadlock)
什么是死锁?
所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象:死锁。
在SQL Server中为了阻止死锁大量充斥在系统中,我们有一个死锁监控的后端线程来帮助解决死锁。
死锁监控线程
如果我们查看sys.dm_os_waiting_tasks,我们可以发现一个系统任务一直处于等待状态:REQUEST_FOR_DEADLOCK_SEARCH。该线程每五秒钟被唤醒,来查看是否有死锁。如果发现死锁,它将结束一个会话。它会杀掉两个会话中的一个,让另一个会话拥有需要的所有资源。
SQL Server会判断,要确保杀掉的是最容易回滚的会话。因为如果SQL Server杀掉一个事务,它所做的任何工作必须回滚到数据库的同步状态。它由LOG USED的值来决定。
我们可以看到上例图杀掉了会话75而不是192,因为会话75使用了648字节日志而会话192使用了944字节。
后端线程每五分钟唤醒检查死锁。如果发现,它遵照上例的流程去决定如何解决。然而,当它第一次唤醒,立马唤醒第二次,确保不是一个嵌套死锁。如果有,会被杀掉,然后返回睡眠状态。下一次唤醒在4.90秒之后(预估唤醒时间花费10毫秒)。每次递减100毫秒,将每秒唤醒10次处理死锁。
如何监控死锁?
方法一:
Windows性能监视器(Performance Monitor)
Object: SQLServer:Locks
Counter: Number of Deadlocks/sec
Instance: _Total
下面的查询提供了自从上次重启以来在本服务器上发生的所有死锁:
SELECT cntr_value AS NumOfDeadLocks FROM sys.dm_os_performance_counters WHERE object_name = ‘SQLServer:Locks‘ AND counter_name = ‘Number of Deadlocks/sec‘ AND instance_name = ‘_Total‘
方法二:
跟踪标识(Trace Flags)1204和1222
Trace Flag 1204至少从SQL Server 2000开始存在。Trace Flag 1222从SQL Server 2005被包含进来。两者的死锁信息被记录到SQL Server错误日志(ERRORLOG)。
方法三:
SQL Server Profiler和服务端的SQL Trace
Trace Event Class: Locks Event Name: Deadlock Graph
像上面示例一样给出一个XML图示。非常容易阅读并找出当前正在进行什么动作。
方法四:
扩展事件(Extended Events)
自从SQL Server 2008开始的监控新方式。扩展事件最终会取代SQL Server Profiler(注意:SQL Server Profiler在被放弃属性列表中)。和SQL Server Profiler一样它提供了相同的XML图示,并且在性能影响上更轻量级。
方法五:
System Health
一个新的默认跟踪,但它不像SQL Server默认跟踪(Default Trace)那样有有限数量的跟踪信息且不能修改。我们可以修改system health的定义,它内置于扩展事件中。不像默认跟踪,system health可以跟踪到刚才已经发生过的死锁信息。我们可以从system health获取这些信息用来分析而不用部署我们自己的扩展事件监控。