关于死锁的问题
Posted
技术标签:
【中文标题】关于死锁的问题【英文标题】:Questions about DeadLock 【发布时间】:2014-12-16 12:27:03 【问题描述】:在这里,我有一些问题。
我会快速简单。
我使用 SQL Server 2008 工作,并且遇到过很多关于死锁的电话。
用户说他们正在工作,然后他们得到一个错误
事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。重新运行事务。
所以我联系了开发人员并告诉他们在查询中添加WITH (NO LOCK)
。
100% 有效。
但是,这样对吗?
有什么可以代替它,或者这是摆脱这些死锁的唯一方法吗?
谢谢
【问题讨论】:
【参考方案1】:好的。所以死锁是两个进程竞争相同的数据,但在更新它(或释放锁)之前等待另一个完成。数据被锁定的原因之一是为了防止“脏读”。即读取过期数据,因为它已经更新了
所以锁定是有原因的,即它是为了保护数据的完整性。仅当您确定您的系统不会因此受到影响时,才应使用 WITH (NO LOCK) 将其关闭。否则你会开始出现数据损坏,即坏数据。
我会说使用 WITH (NO LOCK) 对于只报告的过程是安全的,即选择没有任何后续更新并且与系统的操作无关。对于进行选择然后更新的过程来说不是很好。
根据@idstam 的回答,如果您确实需要选择数据,对其做出一些决定然后进行更新,这些需要尽可能短。即选择和更新之间的时间需要很短,因为那是锁存在的时间,因此是死锁的机会窗口。这在用户查看相同数据的多用户系统中更为普遍。
所以,是的,您可以关闭锁定,但请注意它可能会给您留下不良数据。最好的办法是了解什么是死锁并确定是否可以改进。如果您尝试通过降低隔离级别来最大程度地减少死锁,您将需要使用行版本控制,即每次更新都会检查它是否正在更新上次看到的数据,如果不是(即同时更新)它会抛出错误.
Here is a good MSDN article on how to reduce deadlocks
【讨论】:
【参考方案2】:将数据库设置为使用行级版本控制。
保持交易短暂。
确保在所有地方以相同的顺序使用表格。
预先获得写锁定有时会有所帮助。
【讨论】:
【参考方案3】:这取决于您对读取一致性的关注程度以及对性能的关注程度。
WITH (NO LOCK) - 没有读锁,但您会受到陈旧、不一致的数据的影响 行级别版本 - 行的旧版本保留在“旁边”。这也消除了您正在执行的每个 DML 的额外开销成本的读取锁定。在此处阅读更多信息:http://technet.microsoft.com/en-us/library/ms188277(v=sql.105).aspx
【讨论】:
【参考方案4】:NOLOCK 和 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 可能很有用,但它并不总是正确的答案。这将取决于情况。我认为最大的风险是脏读。 (读取可能由于某种原因回滚的数据。)
你可以在这里阅读更多
http://sqlblog.com/blogs/tamarick_hill/archive/2013/05/06/pros-cons-of-using-read-uncommitted-and-nolock.aspx
希望有帮助
【讨论】:
以上是关于关于死锁的问题的主要内容,如果未能解决你的问题,请参考以下文章