怎么捕获和记录SQL Server中发生的死锁?

我们知道,可以使用SQL Server自带的Profiler工具来跟踪死锁信息。但这种方式有一个很大的敝端,就是消耗很大。据国外某大神测试,profiler甚至可以占到服务器总带宽的35%,所以,在一个繁忙的系统中,使用profiler显然不是一个好主意,下面我介绍两种消耗比较少的方法。其中第二种的消耗最小,在最繁忙的系统中也可使用。第一种最为灵活,可满足多种应用。

 

方法一:利用SQL Server代理(Alert+Job)

 

具体步骤如下:

 

1.首先使用下面的命令,将有关的跟踪标志启用。

[c-sharp]  view plain copy
  1. DBCC TRACEON (3605,1204,1222,-1)  
 

说明:

3605 将DBCC的结果输出到错误日志。

1204 返回参与死锁的锁的资源和类型,以及受影响的当前命令。

1222 返回参与死锁的锁的资源和类型,以及使用了不符合任何 XSD 架构的 XML 格式的受影响的当前命令(比1204更进一步,SQL 2005及以上可用)。

-1 以全局方式打开指定的跟踪标记。

 

以上跟踪标志作用域都是全局,即在SQL Server运行过程中,会一直发挥作用,直到SQL Server重启。

如果要确保SQL Server在重启后自动开启这些标志,可以在SQL Server服务启动选项中,使用 /T 启动选项指定跟踪标志在启动期间设置为开。(位于SQL Server配置管理器->SQL Server服务->SQL Server->属性->高级->启动参数)

 

在运行上面的语句后,当SQL Server中发生死锁时,已经可以在错误日志中看到了,但还不够直观(和其它信息混在一起)。(SSMS -> SQL Server实例 -> 管理 -> SQL Server日志)

 

2.建表,存放死锁记录

[c-sharp]  view plain copy
  1. USE [Cole] --Cole是我的示例数据库,你可以根据实际情况修改。  
  2. GO  
  3. CREATE TABLE DeadLockLog (  
  4. id int IDENTITY (1, 1) NOT NULL,   
  5. LogDate DATETIME,   
  6. ProcessInfo VARCHAR(10),   
  7. ErrorText VARCHAR(MAX)  
  8. )  
  9. GO  
 

 

3.建立JOB

 

新建一个JOB(假设名称为DeadLockJob),在"步骤"中新建一步骤,随便写一个步骤名称,数据库为"Cole"(见2.建表),在"命令"栏中输入以下语句:

 

[c-sharp]  view plain copy
  1. --新建临时表  
  2. IF OBJECT_ID('tempdb.dbo.#ErrorLog') IS Not Null  
  3. DROP TABLE #ErrorLog  
  4. CREATE TABLE #ErrorLog (Id int IDENTITY (1, 1) NOT NULL, a DATETIME, b VARCHAR(10), c VARCHAR(MAX))  
  5. --将当前日志记录插入临时表  
  6. INSERT INTO #ErrorLog EXEC master.dbo.sp_readerrorlog  
  7. --将死锁信息插入用户表  
  8. insert DeadLockLog  
  9. select a, b, c   
  10. from #ErrorLog   
  11. where id >= (select MAX(id) from #ErrorLog WHERE c Like '%Deadlock encountered%')  
  12. DROP TABLE #ErrorLog  
 

 

4.新建警报

 

在"新建警报"窗体的"常规"选项卡中,进行以下设置:

名称:可根据实际自行命名,这里我用DeadLockAlert

类型:选择"SQL Server性能条件警报"

对象:SQLServer:Locks

计数器:Number of Deadlocks/sec

实例:_Total

计数器满足以下条件时触发警报:高于

值:0

设置完成后,应该如下图所示:

 

在"响应"选项卡中,选中"执行作业",并选择步骤3中我们新建的作业(即DeadlockJob)

 

到这里为止,我们已经完成了全部步骤,以后,你就可以随时查询DeadLockLog表,来显示死锁信息了。

 

方法二:利用服务器端跟踪。

具体实现步骤如下:

 

1.编写如下脚本,并执行

[c-sharp]  view plain copy
  1. -- 定义参数  
  2. declare @rc int  
  3. declare @TraceID int  
  4. declare @maxfilesize bigint  
  5. set @maxfilesize = 5   
  6. -- 初始化跟踪  
  7. exec @rc = sp_trace_create @TraceID output, 0, N'e:/DbLog/deadlockdetect', @maxfilesize, NULL   
  8. --此处的e:/dblog/deadlockdetect是文件名(可自行修改),SQL会自动在后面加上.trc的扩展名  
  9. if (@rc != 0) goto error  
  10. -- 设置跟踪事件  
  11. declare @on bit  
  12. set @on = 1  
  13. --下述语句中的148指的是locks:deadlock graph事件(参见sys.trace_events),12指的是spid列(参见sys.trace_columns)  
  14. exec sp_trace_setevent @TraceID, 148, 12, @on    
  15. exec sp_trace_setevent @TraceID, 148, 11, @on  
  16. exec sp_trace_setevent @TraceID, 148, 4, @on  
  17. exec sp_trace_setevent @TraceID, 148, 14, @on  
  18. exec sp_trace_setevent @TraceID, 148, 26, @on  
  19. exec sp_trace_setevent @TraceID, 148, 64, @on  
  20. exec sp_trace_setevent @TraceID, 148, 1, @on  
  21. -- 启动跟踪  
  22. exec sp_trace_setstatus @TraceID, 1  
  23. -- 记录下跟踪ID,以备后面使用  
  24. select TraceID = @TraceID  
  25. goto finish  
  26. error:   
  27. select ErrorCode=@rc  
  28. finish:   
  29. go  
 

运行上述语句后,每当SQL Server中发生死锁事件,都会自动往文件e:/DbLog/deadlockdetect.trc中插入一条记录。

 

2.暂停和停止服务器端跟踪

 

如果要暂停上面的服务器端跟踪,可运行下面的语句:

exec sp_trace_setstatus 1, 0 --第一个参数表示TraceID,即步骤1中的输出参数。第二个参数表示将状态改为0,即暂停

如果要停止上面的服务器端跟踪,可运行下面的语句:

exec sp_trace_setstatus 1, 2 --第一个参数表示TraceID,即步骤1中的输出参数。第二个参数表示将状态改为2,即停止

 

3.查看跟踪文件内容

 

对于上面生成的跟踪文件(e:/DbLog/deadlockdetect.trc),可通过两种方法查看:

1).执行t-sql命令

[c-sharp]  view plain copy
  1. select * from fn_trace_gettable('e:/DbLog/deadlockdetect.trc',1)  
 

结果中的TextData列即以XML的形式返回死锁的详细信息。

2).在SQL Server Profiler中打开。

依次 进入Profiler -> 打开跟踪文件 ->选择e:/DbLog/deadlockdetect.trc,就可以看到以图形形式展现的死锁信息了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值