日期:2014-05-17  浏览次数:20443 次

一个死锁问题
存储过程用了事务,代码如下:
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

    ...

------解决方案---