常见的四种解决死锁的方法
方法一、调整索引,以调整执行计划,减少锁的申请数目,从而消除死锁
如果死锁的双方不会申请对方要申请的锁,那么死锁也不会发生。如果
数据库设计者能够引导SQL使用seek的执行计划,只读取要返回的数据,
那么申请的锁数量会大大降低,死锁的几率也会减少
(1)死锁双方处理的数据本身没有交叉
如果双方都要修改或返回同样的数据,那么再优化索引,可能也没有用处
(2)DBA要有权力在数据库里调整索引设计
方法二、使用“nolock”参数,让select 语句不要申请S锁,减少锁的申请数目,从而消除死锁
很多死锁发生在S锁上面,我们可以通过在语句里加“nolock”参数的方法,让select语句不要去申请S锁,死锁自然也会消失
这个方法解决死锁可以说是立竿见影,所以很多用户很喜欢使用它
但是缺点很明显,with (nolock)这个参数意味着,select语句将能接收脏读,这是SQLServer支持的最低一级事务隔离级别。用户要能够理解他的副作用,并且能够接受,才能使用
这种方法只能解决S锁参与的死锁问题,如果死锁发生在U锁或X锁上,with (nolock)没有帮助
SELECT * FROM [dbo].[Employee_Demo_Heap] WITH (NOLOCK)
方法三、升级锁粒度,将死锁转化为一个阻塞问题
死锁产生的原因是双方都申请到了一个资源,同时又要申请对方的资源。
如果一方一个资源都没有申请到,那么发生的就是阻塞,而不是死锁
从这个角度讲,如果能想办法让一方被另一方阻塞住,什么资源都申请不到
那死锁就不会发生
从上面的例子里,死锁发生在同一个page上的不同rid上。如果语句直接申请Page
级别的锁,同时就只能有一个人得到锁资源,而另一个人会被阻塞住。因此,
使用pagelock这个参数,也能解决死锁问题。
这种方法虽然不会降低事务隔离级别,但是语句更容易被阻塞住,最终
的并发度难免受到影响。因此实际上也是一种粗鲁的方法。没有第一种
通过加索引的方法那么精细。如果能用第一种方法,还是使用第一种方法
比较负责任
SELECT * FROM [dbo].[Employee_Demo_Heap] WITH (PAGLOCK)
方法四、使用快照隔离级别
由于这个死锁里有S锁参与,这里把事务隔离级别从默认的已提交读
改成快照隔离级别,对缓解死锁也会有很好帮助。
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
文章转载自:
https://www.cnblogs.com/lyhabc/articles/3222228.html
文章经作者授权转载,版权归原文作者所有
图片来源于网络,侵权必删!




