处理sql server的死锁 [kill spid]

1 篇文章 0 订阅
1 篇文章 0 订阅

出现死锁的解决办法

  1. 在master中创建查看死锁的存储过程

    1. use master  
    2. go  
    3. create procedure sp_who_lock  
    4. as  
    5. begin  
    6. declare @spid int,@bl int,  
    7.         @intTransactionCountOnEntry  int,  
    8.         @intRowcount    int,  
    9.         @intCountProperties   int,  
    10.         @intCounter    int  
    11.   
    12.  create table #tmp_lock_who (  
    13.  id int identity(1,1),  
    14.  spid smallint,  
    15.  bl smallint)  
    16.    
    17.  IF @@ERROR<>0 RETURN @@ERROR  
    18.    
    19.  insert into #tmp_lock_who(spid,bl) select  0 ,blocked  
    20.    from (select * from sysprocesses where  blocked>0 ) a   
    21.    where not exists(select * from (select * from sysprocesses where  blocked>0 ) b   
    22.    where a.blocked=spid)  
    23.    union select spid,blocked from sysprocesses where  blocked>0  
    24.   
    25.  IF @@ERROR<>0 RETURN @@ERROR   
    26.     
    27. -- 找到临时表的记录数  
    28.  select  @intCountProperties = Count(*),@intCounter = 1  
    29.  from #tmp_lock_who  
    30.    
    31.  IF @@ERROR<>0 RETURN @@ERROR   
    32.    
    33.  if @intCountProperties=0  
    34.   select '现在没有阻塞和死锁信息' as message  
    35.   
    36. -- 循环开始   
    37. while @intCounter <= @intCountProperties  
    38. begin  
    39. -- 取第一条记录  
    40.   select  @spid = spid,@bl = bl  
    41.   from #tmp_lock_who where Id = @intCounter   
    42.  begin  
    43.   if @spid =0   
    44.       select '引起数据库死锁的是: 'CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'  
    45.   else  
    46.       select '进程号SPID:'CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'  
    47.  DBCC INPUTBUFFER (@bl )  
    48.  end  
    49.   
    50. -- 循环指针下移   
    51.  set @intCounter = @intCounter + 1  
    52. end  
    53.   
    54. drop table #tmp_lock_who  
    55.   
    56. return 0  
    57. end  

在master中创建删除指定数据库的死锁的存储过程

  1. use master  
  2. go  
  3.   
  4. if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_killspid]'and OBJECTPROPERTY(id, N'IsProcedure') = 1)  
  5. drop procedure [dbo].[p_killspid]  
  6. GO  
  7.   
  8. create proc p_killspid  
  9. @dbname varchar(200)    --要关闭进程的数据库名  
  10. as    
  11.     declare @sql  nvarchar(500)    
  12.     declare @spid nvarchar(20)  
  13.   
  14.     declare #tb cursor for  
  15.         select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)  
  16.     open #tb  
  17.     fetch next from #tb into @spid  
  18.     while @@fetch_status=0  
  19.     begin    
  20.         exec('kill '+@spid)  
  21.         fetch next from #tb into @spid  
  22.     end    
  23.     close #tb  
  24.     deallocate #tb  
  25. go 
  1. 查看死锁

  2. [sql]
    1. exec master..sp_who_lock  
  3. exec master..sp_who_lock
  4. 删除死锁

    1. exec master..p_killspid 'dbname'  

避免死锁

  1. 按同一顺序访问对象

    如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务获得 Supplier 表上的锁,然后获得 Part 表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在 Supplier 表上。第一个事务提交或回滚后,第二个事务继续进行。不发生死锁。将存储过程用于所有的数据修改可以标准化访问对象的顺序。

  2. 避免事务中的用户交互

    避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户去吃午餐了或者甚至回家过周末了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

  3. 保持事务简短并在一个批处理中

    在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。

    保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

  4. 使用低隔离级别

    确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

    1. ALTER DATABASE [dbname]  
    2. SET READ_COMMITTED_SNAPSHOT ON  

使用绑定连接

使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值