解决方案 »

  1.   

    从图形界面看不出死锁对应的SQL语句,
    建议启用1222跟踪标记,当发生死锁时会将详细的死锁日志记录在SQL日志中,便于分析..
      

  2.   

    看左上角和右下角:
     服务器进程 ID=62,为同一个spid会话;
    所有者 ID=362976,为同一个进程中的事务;
    执行上下文 ID=1或3,都是2个子线程;可能的原因是:同一个事务中,进行了多线程执行,并且有2个连接并发访问。
    此外,更多原因还包括,事务中多次访问相同的资源。
      

  3.   

    似乎从图中看出不是这样的。
    应该是进程62和63各自持有一个页级锁,同时,在相互等待对方的锁释放。我的存储过程主要部分是这样的:
    BEGIN TRAN UPDATE SingUserLogInfo SET 
    CookieGuid=@CookieGuid
    ,loginTime=@loginTime 
    WHERE UserName=@UserName 
    and Usertype=@usertype IF @@ROWCOUNT=0
    insert into SingUserLogInfo(UserName,CookieGuid,usertype,loginTime)
    values(@UserName,@CookieGuid,@usertype,@loginTime) COMMIT TRAN
    最后排查出来是缺少索引导致的死锁,但是我还是不太明白单个表也能死锁?
      

  4.   

    似乎从图中看出不是这样的。
    应该是进程62和63各自持有一个页级锁,同时,在相互等待对方的锁释放。我的存储过程主要部分是这样的:
    BEGIN TRAN UPDATE SingUserLogInfo SET 
    CookieGuid=@CookieGuid
    ,loginTime=@loginTime 
    WHERE UserName=@UserName 
    and Usertype=@usertype IF @@ROWCOUNT=0
    insert into SingUserLogInfo(UserName,CookieGuid,usertype,loginTime)
    values(@UserName,@CookieGuid,@usertype,@loginTime) COMMIT TRAN
    最后排查出来是缺少索引导致的死锁,但是我还是不太明白单个表也能死锁?
    我这当前页有类似的设计:更新的时候,UserName=@UserName    and Usertype=@usertype 只锁定这些资源,其他资源还是可以访问的。
    再插入使,也会更新聚集索引。当并发执行时就可能死锁。
    如果要不死锁,就得序列化。存储过程设置序列化的事务级别,或者 tablock  holdlock 让事务保存到结束
      

  5.   

    我觉得应该分析一下,为啥持有的是页锁?第一条UPDATE语句更新的记录非常多么?可以按照之前几位的建议,把死锁跟踪标记打开,获取更详细的信息。
      

  6.   

    如果是sqlserver 2008以上改用merge 改写这一段代码应该可以解决这个死锁问题