SQL Server中如何减少死锁,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
减少SQLServer死锁的方法有哪些
如事务1的线程T1具有表A上的排它锁,事务2的线程T2具有表B上的排它锁,并且之后需要表A上的锁。事务2无法获得这一锁,因为事务1已拥有它。事务2被阻塞,等待事务1。然后,事务1需要表B的锁,但无法获得锁,因为事务2将它锁定了。事务在提交或回滚之前不能释放持有的锁。因为事务需要对方控制的锁才能继续操作,所以它们不能提交或回滚,这样数据库就会发生死锁了。
如在编写存储过程的时候,由于有些存储过程事务性的操作比较频繁,假如先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。假如无意中某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。而且死锁一般是不太容易被发现的。
假如服务器上经常出现这种死锁情况,就会降低服务器的性能,所以应用程序在使用的时候,我们就需要对其进行跟踪,使用sp_who和sp_who2来确定可能是哪些用户阻塞了其他用户,我们还可以用下面的存储过程来跟踪具体的死锁执行的影响:
createproceduresp_who_lock
as
begin
declare@spidint,@blint,
@intTransactionCountOnEntryint,
@intRowcountint,
@intCountPropertiesint,
@intCounterint
createtable#tmp_lock_who(idintidentity(1,1),spidsmallint,blsmallint)
IF@@ERROR<>0RETURN@@ERROR
insertinto#tmp_lock_who(spid,bl)select0,blocked
from(select*fromsysprocesseswhereblocked>0)a
wherenotexists(select*from(select*fromsysprocesseswhereblocked>0)b
wherea.blocked=spid)
unionselectspid,blockedfromsysprocesseswhereblocked>0
IF@@ERROR<>0RETURN@@ERROR
--找到临时表的记录数
select@intCountProperties=Count(*),@intCounter=1
from#tmp_lock_who
IF@@ERROR<>0RETURN@@ERROR
if@intCountProperties=0
select’现在没有阻塞和死锁信息’asmessage
--循环开始
while@intCounter<=@intCountProperties begin --取第一条记录 select@spid=spid,@bl=bl from#tmp_lock_whowhereid=@intCounter begin if@spid=0 select’引起数据库死锁的是:’+CAST(@blASVARCHAR(10))+’进程号,其执行的SQL语法如下’ else select’进程号SPID:’+CAST(@spidASVARCHAR(10))+’被’+’进程号SPID:’+CAST(@blASVARCHAR(10))+’阻塞,其当前进程执行的SQL语法如下’ DBCCINPUTBUFFER(@bl) end --循环指针下移 set@intCounter=@intCounter+1 end droptable#tmp_lock_who return0 end 减少SQLServer死锁的方法有哪些 我们只需要通过在查询分析器里面执行sp_who_lock,就可以具体捕捉到执行的堵塞进程,这时我们就可以对对应的SQL语句或者存储过程进行性能上面的改进及设计。[Page] 所以我们在数据库设计的时候,虽然不能完全避免死锁,但可以使死锁的数量尽量减少。增加事务的吞吐量并减少系统开销,因为只有很少的事务,所以就得遵循下面的原则: 按同一顺序访问对象 假如所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。在写SQL语句或存储过程的时候,就需要按照顺序在两个并发事务中先获得表A上的锁,然后获得表B上的锁,当第一个事务完成之前,另一个事务被阻塞在表A上。第一个事务提交或回滚后,第二个事务继续进行,而不能在语句里面写先获得表B上的锁,然后再获得表A的锁。 避免事务中的用户交互 避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,假如事务正在等待用户输入,而用户就去做别的事了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。 保持事务简短并在一个批处理中 在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。 使用低隔离级别 确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。 使用绑定连接 使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。
下面有一些对死锁发生的一些建议:
1)对于频繁使用的表使用集簇化的索引;
2)设法避免一次性影响大量记录的T-SQL语句,特别是INSERT和UPDATE语句;
3)设法让UPDATE和DELETE语句使用索引;
4)使用嵌套事务时,避免提交和回退冲突;
5)对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select*fromtableA(nolock)。
看完上述内容,你们掌握SQL Server中如何减少死锁的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。