码迷,mamicode.com
首页 > 其他好文 > 详细

Resolve Block

时间:2015-07-10 18:35:47      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

SQL Server能够自动检测到死锁,死锁检测是由一个称为锁监视器的线程单独执行的。SQL Server每5S钟执行一次检测,检测到死锁后,SQL Server通过选择其中一个线程作为deadlock victim来解除死锁。SQL Server终止deadlock victim线程当前执行的处理,回滚其事务,并将1205 错误返回到应用程序。默认情况下,SQL Server选择运行回滚开销最小的事务的线程作为deadlock victim。

SQL Server对阻塞和死锁的解决方案不同,对于死锁,SQL Server负责检测和解除,但是对于阻塞,SQL Server不会自动检测和解除。阻塞是单向的,如果两个事务互相阻塞,则阻塞变成死锁。当一个事务A申请一个被事务B锁定的资源上的封锁时,发出封锁请求的事务A会一直等待,直到该锁被事务B释放,事务A申请到封锁为止。此时,事务B可能正在进行大量的修改操作,不能释放封锁。如果没有设置Lock_timeout,那么事务A会一直等待,直到事务B处理完成,释放封锁,事务A申请到封锁,阻塞才会自动解除。阻塞状态往往会持续很长时间,SQL Server也不会做出干预,而对于死锁,SQL Server内置死锁的检测方案,至少5S会消除一个Deadlock,对性能的影响往往没有阻塞严重。

如何检测阻塞?通过查询视图Master.sys.sysprocesses,筛选条件是Blocked>0,并且Waittime 很大,“很大”是一个需要斟酌的值。当检测到阻塞之后,可以单纯的将阻塞的线程Kill,保障被阻塞线程的运行,这是一种思路,虽然不一定是最好的。

--代码没有进行测试,后续完善
if object_id(tempdb..#tmpblocked) is not null
drop table #tmpblocked

create table #tmpblocked
(
id int not null identity(1,1),
blocked int
)

--get blocked thread spid
;with cte as
(
select spid,blocked
from master.sys.sysprocesses with(nolock)
where blocked>0
)
insert into #tmpblocked(blocked)
select a.blocked
from cte a with(nolock)
inner join cte b with(nolock)
on a.blocked<>b.spid


declare @i int
declare @maxid int
declare @blockid int
declare @sql Nvarchar(max)

select @maxid=max(id),@i=1
from #tmpblocked

while @i<=@maxid
begin
    select @blockid=blocked
    from #tmpblocked
    where id=@i

    set @sql=Nkill + cast(@blockid as Nvarchar)
    
    exec sys.sp_executesql @sql

    set @i=@i+1
end 

 

单纯的Kill阻塞的线程不一定是最好的。在Kill阻塞的线程时,SQL Server终止该线程当前执行的处理,回滚其事务。如果被kill的线程正在做大批量数据的更新操作,其事务的回滚将会持续很长世间,而被阻塞的事务必须等待其回滚完成,才能申请封锁,对性能的影响比较严重。

如何有效的解除阻塞?需要捕捉阻塞的现场信息,分析阻塞产生的原因,有针对性的解除阻塞。

 

Resolve Block

标签:

原文地址:http://www.cnblogs.com/ljhdo/p/4636423.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!