存储过程A,自己锁自己。   存储过程B和存储过程C相互锁定。问题如下截图所示:问题一:存储过程为什么自己锁自己???   是因为 “sp_who_lock”这个存储过程检查的不对吗???问题二: 我该怎么样找到死锁发生的位置?  比如提示第333行。      但是存储过程的执行方式是, C过程调用 D过程,D过程调用 E过程 这种方式。  显示行号以后,  我应该从哪一行开始数???     从 Create proc语句,还是声明变量 declare ,还是 as begin  ...  中间的隔开的行又算不算???  
     SQLServer提示的行号,应该怎么看???   求大神帮忙啊。

解决方案 »

  1.   

    sp_who_lock   存储过程CREATE procedure sp_who_lock   
    as     
    begin     
       declare @spid int     
       declare @blk int     
       declare @count int     
       declare @index int     
       declare @lock tinyint      
       set @lock=0      
       create table #temp_who_lock      
     (      
      id int identity(1,1),      
      spid int,      
      blk int     
     )      
     if @@error<>0 return @@error      
     insert into #temp_who_lock(spid,blk)      
     select 0 ,blocked       
     from (select * from master..sysprocesses where blocked>0)a      
     where not exists(select * from  master..sysprocesses where a.blocked =spid and blocked>0)      
     union select spid,blocked from  master..sysprocesses where blocked>0      
     if @@error<>0 return @@error      
     select @count=count(*),@index=1 from #temp_who_lock      
     if @@error<>0 return @@error      
     if @count=0      
     begin     
      select '没有阻塞和死锁信息'     
      return 0      
     end     
     while @index<=@count      
     begin     
      if exists(select 1 from #temp_who_lock a where id>@index and exists(select 1 from #temp_who_lock where id<=@index and a.blk=spid))      
      begin     
       set @lock=1      
       select @spid=spid,@blk=blk from #temp_who_lock where id=@index     
       select '引起数据库死锁的是: '+ CAST(@spid AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'     
       select  @spid, @blk    
       dbcc inputbuffer(@spid)      
       dbcc inputbuffer(@blk)      
      end     
      set @index=@index+1      
     end     
     if @lock=0       
     begin     
      set @index=1      
      while @index<=@count      
      begin     
       select @spid=spid,@blk=blk from #temp_who_lock where id=@index     
       if @spid=0      
        select '引起阻塞的是:'+cast(@blk as varchar(10))+ '进程号,其执行的SQL语法如下'     
       else      
        select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@blk AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'     
       dbcc inputbuffer(@spid)    
       dbcc inputbuffer(@blk)      
       set @index=@index+1      
      end     
     end     
     drop table #temp_who_lock      
     return 0      
    end
      

  2.   

    我看你发的这个图,都是同一个过程,阻塞了自己,应该不是问题。 也不存在死锁。等你的过程执行一段时间,你再看看。或者是,你这两个过程互相阻塞了,建议你查查你的这两个 usp  开头的过程。梳理一下执行流程。
      

  3.   

    注意,sp_who_lock 输出的是 死锁,而非阻塞,也就是说 你的存储过程 的2次执行,比如:A 、B,可能是 A阻塞了B,而同时B阻塞了A,所以A、B之间发生了死锁,才会导致上面的问题。具体问题要具体分析,最好把代码贴出来
      

  4.   


    把所有的SELECT改成以下语法SELECT * FROM 表名 WITH (NOLOCK)
      

  5.   

    我一直对这个存储过程有点怀疑,最起码在2005以后应该用dmv来查死锁。或者直接看错误日志,2008以后甚至可以用扩充事件来实现。另外,自己死锁是可能的,其中一个情景是存储过程进行了并行操作,进程之间发生了死锁。这个以前有个朋友问过我,结果他说优化一下脚本,让它不需要进行并行操作,就好了。
      

  6.   

    sp_who_lock是第三方开发的存储过程,运行结果仅供参考.
    建议启用1222跟踪标记,发生死锁后可查看SQL日志,有详细的死锁日志信息供分析.