找到死锁的spid 并杀掉

 尽管死锁不能完全避免,但遵守特定的编码惯例可以将发生死锁的机会降至最低。将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务:    
  回滚,撤消事务执行的所有工作。    
  由于死锁时回滚而由应用程序重新提交。    
  下列方法有助于将死锁减至最少:    
  按同一顺序访问对象。    
  避免事务中的用户交互。    
  保持事务简短并处于一个批处理中。    
  使用较低的隔离级别。    
  使用基于行版本控制的隔离级别。    
  将   READ_COMMITTED_SNAPSHOT   数据库选项设置为   ON,使得已提交读事务使用行版本控制。    
  使用快照隔离。    
  使用绑定连接。    
  按同一顺序访问对象    
  如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务先获取   Supplier   表上的锁,然后获取   Part   表上的锁,则在其中一个事务完成之前,另一个事务将在   Supplier   表上被阻塞。当第一个事务提交或回滚之后,第二个事务将继续执行,这样就不会发生死锁。将存储过程用于所有数据修改可以使对象的访问顺序标准化。    
  避免事务中的用户交互    
  避免编写包含用户交互的事务,因为没有用户干预的批处理的运行速度远快于用户必须手动响应查询时的速度(例如回复输入应用程序请求的参数的提示)。例如,如果事务正在等待用户输入,而用户去吃午餐或甚至回家过周末了,则用户就耽误了事务的完成。这将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚后才会释放。即使不出现死锁的情况,在占用资源的事务完成之前,访问同一资源的其他事务也会被阻塞。    
  保持事务简短并处于一个批处理中    
  在同一数据库中并发执行多个需要长时间运行的事务时通常会发生死锁。事务的运行时间越长,它持有排他锁或更新锁的时间也就越长,从而会阻塞其他活动并可能导致死锁。    
  保持事务处于一个批处理中可以最小化事务中的网络通信往返量,减少完成事务和释放锁可能遭遇的延迟。    
  使用较低的隔离级别    
  确定事务是否能在较低的隔离级别上运行。实现已提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如已提交读)比使用较高的隔离级别(例如可序列化)持有共享锁的时间更短。这样就减少了锁争用。    
  使用基于行版本控制的隔离级别    
  如果将   READ_COMMITTED_SNAPSHOT   数据库选项设置为   ON,则在已提交读隔离级别下运行的事务在读操作期间将使用行版本控制而不是共享锁。    
  注意:    
  某些应用程序依赖于已提交读隔离的锁定和阻塞行为。对于这些应用程序,要启用此选项必须进行一些更改。    
  快照隔离也使用行版本控制,该级别在读操作期间不使用共享锁。必须将   ALLOW_SNAPSHOT_ISOLATION   数据库选项设置为   ON,事务才能在快照隔离下运行。    
  实现这些隔离级别可使得在读写操作之间发生死锁的可能性降至最低。    
  使用绑定连接    
  使用绑定连接,同一应用程序打开的两个或多个连接可以相互合作。可以像主连接获取的锁那样持有次级连接获取的任何锁,反之亦然。这样它们就不会互相阻塞。 

 

 

 

找到死锁的spid 并杀掉
 
use master --必须在master数据库中创建
go

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_lockinfo]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_lockinfo]
GO

/*--处理死锁

查看当前进程,或死锁进程,并能自动杀掉死进程

因为是针对死锁的,所以如果有死锁进程,只能查看死锁进程
当然,你可以通过参数控制,不管有没有死锁,都只查看死锁进程

感谢: caiyunxia,jiangopen 两位提供的参考信息

--邹建 2004.04(引用请保留此信息)--*/

/*--调用示例

exec p_lockinfo
--*/
create proc p_lockinfo
@kill_lock_spid bit=1, --是否杀掉死锁的进程,1 杀掉, 0 仅显示
@show_spid_if_nolock bit=1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示
as
set nocount on
declare @count int,@s nvarchar(1000),@i int
select id=identity(int,1,1),标志,
进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,
数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu,
登陆时间=login_time,打开事务数=open_tran, 进程状态=status,
工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess,
域名=nt_domain,网卡地址=net_address
into #t from(
select 标志='死锁的进程',
spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,
status,hostname,program_name,hostprocess,nt_domain,net_address,
s1=a.spid,s2=0
from master..sysprocesses a join (
select blocked from master..sysprocesses group by blocked
)b on a.spid=b.blocked where a.blocked=0
union all
select '|_牺牲品_>',
spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
status,hostname,program_name,hostprocess,nt_domain,net_address,
s1=blocked,s2=1
from master..sysprocesses a where blocked<>0
)a order by s1,s2

select @count=@@rowcount,@i=1

if @count=0 and @show_spid_if_nolock=1
begin
insert #t
select 标志='正常的进程',
spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,
open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address
from master..sysprocesses
set @count=@@rowcount
end

if @count>0
begin
create table #t1(id int identity(1,1),a nvarchar(30),b Int,EventInfo nvarchar(255))
if @kill_lock_spid=1
begin
declare @spid varchar(10),@标志 varchar(10)
while @i<=@count
begin
select @spid=进程ID,@标志=标志 from #t where id=@i
insert #t1 exec('dbcc inputbuffer('+@spid+')')
if @@rowcount=0 insert #t1(a) values(null)
if @标志='死锁的进程' exec('kill '+@spid)
set @i=@i+1
end
end
else
while @i<=@count
begin
select @s='dbcc inputbuffer('+cast(进程ID as varchar)+')' from #t where id=@i
insert #t1 exec(@s)
if @@rowcount=0 insert #t1(a) values(null)
set @i=@i+1
end
select a.*,进程的SQL语句=b.EventInfo
from #t a join #t1 b on a.id=b.id
order by 进程ID
end
set nocount off
go

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值