一个死锁问题
存储过程用了事务,代码如下:
begin tran
update t1 set Status = 1,a2 = getdate() where nID = @nID
select @UserPRI = isnull(UsePRI,3) from t1 where nID = @nID
if(@UserPRI = 1)
BEGIN
update t2 set c2= @nID where c1 = @c1
END
这个存储过程调用非常频繁,经常发生死锁,死锁日志如下:
<ridlock fileid="1" pageid="153417" dbid="13" objectname="" id="lock17136a400" mode="X" associatedObjectId="72057594043957248">
<owner-list>
<owner id="process584e508" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process5844508" mode="U" requestType="wait" />
</waiter-list>
</ridlock>
<ridlock fileid="1" pageid="153040" dbid="13" objectname="" id="lock44b39a300" mode="X" associatedObjectId="72057594043957248">
<owner-list>
<owner id="process5844508" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process584e508" mode="S" requestType="wait" />
</waiter-list>
</ridlock>
</resource-list>
死锁日志说的都是t1表,两个对存储过程的调用都是拥有X锁,说明更新了数据;
有俩疑问:
1,第一个调用者拥有pageid="153417"的page页的x锁,修改完查询时还是查询的刚才修改的记录(条件都是nID = @nID),为什么查询要去申请另一个page( pageid="153040")呢?
2,修改完之后,进行查询,为什么要申请U锁呢?
对这个实在不熟,请指教
[解决办法]
try this,
begin tran
select * into #t from t1 where 1=2
update t1
set Status=1,
a2=getdate()
output inserted.* into #t
where nID=@nID
select @UserPRI=isnull(UsePRI,3)
from #t
if(@UserPRI = 1)
BEGIN
update t2 set c2= @nID where c1 = @c1
END
...
[解决办法]
象你这种问题,如果能够很好的使用merge去udpate,就不存在查询和更新次完成,那也不存在锁的问题了.
有关merge的使用,这是个完整的例子:
http://bbs.csdn.net/topics/390597779