查数据库死锁的实际例子

一个项目上的数据库宕掉了,开始非说是我的工作流造成的。我也不是数据库的专家,只能硬着头皮边学边用的查了,怀疑是数据库死锁,就沿着这个方向前进。

首先sa登录查询分析器,执行Dbcc traceon(1204, 3605, -1),其中参数1204代表返回参与死锁的锁的类型以及当前受影响的命令,3605代表trace到的信息必须记录到日志中,-1代表返回当前所有打开的跟踪标记的状态。有几点要注意,1、事件探查器是跟不出死锁的sql的,因为它只是记录执行过的sql,而这些在事务里面死锁的sql都会被回滚的;2、只有在打开这些标记后数据库才会记录日志,打开这些标记会影响数据库性能,记得用完了使用Dbcc traceoff(标记号)关掉。

接着就是再现这个死锁了,让实施人员在远程找5、6个人同时点这个功能,嘿嘿,不错,一下子就出来了。将数据库日志发过来,一般在Program Files\Microsoft SQL Server\MSSQL.4\MSSQL\LOG\ERRORLOG下。打开文件仔细看发现下面的日志。

2008-05-31 10:10:46.20 spid5s      Node:1

2008-05-31 10:10:46.20 spid5s      RID: 5:1:6815:21               CleanCnt:3 Mode:X Flags: 0x2
2008-05-31 10:10:46.20 spid5s       Grant List 2:
2008-05-31 10:10:46.20 spid5s         Owner:0x3711E420 Mode: X        Flg:0x0 Ref:1 Life:02000000 SPID:59 ECID:0 XactLockInfo: 0x387A26FC
2008-05-31 10:10:46.20 spid5s         SPID: 59 ECID: 0 Statement Type: DELETE Line #: 133
2008-05-31 10:10:46.20 spid5s         Input Buf: RPC Event: Proc [Database Id = 5 Object Id = 1254295528]
2008-05-31 10:10:46.20 spid5s       Requested By:
2008-05-31 10:10:46.20 spid5s         ResType:LockOwner Stype:'OR'Xdes:0x533EBC80 Mode: S SPID:67 BatchID:0 ECID:0 TaskProxy:(0x1F092374) Value:0x2962ae40 Cost:(0/0)
2008-05-31 10:10:46.20 spid5s     
2008-05-31 10:10:46.20 spid5s      Node:2

2008-05-31 10:10:46.20 spid5s      KEY: 5:72057594056212480 (fc0199b9be7a) CleanCnt:2 Mode:S Flags: 0x0
2008-05-31 10:10:46.20 spid5s       Grant List 2:
2008-05-31 10:10:46.20 spid5s         Owner:0x2028AD80 Mode: S        Flg:0x0 Ref:1 Life:00000000 SPID:67 ECID:0 XactLockInfo: 0x533EBCA4
2008-05-31 10:10:46.20 spid5s         SPID: 67 ECID: 0 Statement Type: SELECT Line #: 1
2008-05-31 10:10:46.20 spid5s         Input Buf: RPC Event: Proc [Database Id = 5 Object Id = 484053356]
2008-05-31 10:10:46.20 spid5s       Requested By:
2008-05-31 10:10:46.20 spid5s         ResType:LockOwner Stype:'OR'Xdes:0x387A26D8 Mode: X SPID:59 BatchID:0 ECID:0 TaskProxy:(0x576FE374) Value:0x1eb9ad20 Cost:(0/84)
2008-05-31 10:10:46.20 spid5s     
2008-05-31 10:10:46.20 spid5s      Victim Resource Owner:
2008-05-31 10:10:46.20 spid5s       ResType:LockOwner Stype:'OR'Xdes:0x533EBC80 Mode: S SPID:67 BatchID:0 ECID:0 TaskProxy:(0x1F092374) Value:0x2962ae40 Cost:(0/0)

Node1(SPID:59)拥有了一个资源的排他锁Mode: X ,而需要申请另一个资源的共享锁Mode: S,Node2(SPID:67)拥有了后一个资源的共享锁,请求前一个资源的排他锁。根据学校里的零星知识,还是能明白这个道理的。照理说这种情况是不会死锁的,但是如果在事务里,共享锁也会在事务结束以后才释放。

联机丛书上有一些信息可以利用来看这段日志。

类型列

"类型"列显示当前锁定的资源类型。

资源类型
描述

RID
用于锁定表中的一行的行标识符。

KEY
索引中的行锁。用于保护可串行事务中的键范围。

PAG
数据或索引页。

EXT
相邻的八个数据页或索引页构成的一组。

TAB
包括所有数据和索引在内的整个表。

DB
数据库。

资源列

"资源"列提供有关正被锁定资源的信息。

资源类型
描述

RID
表内已锁定行的行标识符。行由 fileid:page:rid 组合进行标识,其中,rid 是页中的行标识符。

KEY
SQL Server 内部使用的十六进制数字。

PAG
页码。页由 fileid:page 组合进行标识,其中,fileid 是 sysfiles 表中的 fileid,而 page 是该文件内的逻辑页码。

EXT
正被锁定的扩展盘区中的第一个页码。页由 fileid:page 组合进行标识。

TAB
由于 ObjId 列已包含表的对象 ID,所以没有提供任何信息。

DB
由于 dbid 列已包含数据库的数据库 ID,所以没有提供任何信息。

sp_lock 的结果集内,锁定的 RID 资源类型中的资源描述为 1:1225:2。这表明在 fileid 1 内、页码为 1225 的页中、行标识符为 2 的行上应用了锁。

最关键的信息我认为是

[Database Id = 5 Object Id = 1254295528]和[Database Id = 5 Object Id = 484053356]
指明了加锁的两个对象。

select  db_name(5)  结果为 cwbase_zclzj
连接 cwbase_zclzj帐套,
select object_name(484053356)  结果为  : erp_LS_BillCodeRule_GenerateNewBillCode
select object_name(1254295528)  结果为: erp_LS_BillFlowNoRecords_NewRecordSave

原来是两个存储过程搞得鬼,在生成单据编号的时候出现了死锁,因为两者是放在同一个事物中,也就验证了我们上面的猜想。简单的处理办法是不要放到同一个事物中,其他的办法就让负责维护的同事去管吧。

就写到这里,其实日志里面的大部分咚咚还是看不懂,等待高人给予解释。如果分析中有什么不对的,也请各位回复指出,我也进一步学习一下。谢谢!

转载于:https://www.cnblogs.com/ipointer/archive/2008/06/05/1214005.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值