【问题标题】:SQL Server deadlocks between select/update or multiple selects选择/更新或多选之间的 SQL Server 死锁
【发布时间】:2009-03-19 11:48:37
【问题描述】:

所有关于 SQL Server 死锁的文档都谈到了操作 1 锁定资源 A 然后尝试访问资源 B 并且操作 2 锁定资源 B 并尝试访问资源 A 的场景。

但是,在我们一些繁忙的应用程序中,我经常看到选择和更新之间甚至多个选择之间出现死锁。我发现死锁跟踪输出的一些更精细的点非常难以理解,但我真的很想了解什么会导致两个单一操作之间的死锁。当然,如果一个选择有一个读锁,更新应该在获得排他锁之前等待,反之亦然?

这发生在 SQL Server 2005 上,但我认为这并不重要。

【问题讨论】:

    标签: sql-server sql-server-2005 deadlock


    【解决方案1】:

    发生这种情况是因为选择锁定了两个不同的索引,同时更新以相反的顺序锁定了相同的索引。 select 需要两个索引,因为第一个索引没有覆盖它需要访问的所有列;更新需要两个索引,因为如果您更新索引的键列,您需要锁定它。

    http://blogs.msdn.com/bartd/archive/2006/09/25/770928.aspx 有一个很棒的解释。建议的修复方法包括添加一个涵盖 select 需要的所有列的索引、切换到快照隔离或显式强制 select 获取它通常不需要的更新锁。

    【讨论】:

    【解决方案2】:

    我很惊讶没有人提到WITH (UPDLOCK) 锁定提示。如果您遇到涉及例如的死锁,这将非常有用。两个并行运行的选择插入对。

    在 SQL Server 中,如果您使用 WITH (UPDLOCK) 发出选择,则第二个选择将等到第一个选择完成。否则它们会获得共享锁,并且当它们同时尝试升级到独占锁时,它们会死锁。

    【讨论】:

    • Rolf Kristensen 在他的回答中完美地解释了WITH (UPDLOCK)
    【解决方案3】:

    我的猜测是select-statement需要一个read-lock,当你附带update-statement时,它需要升级到write-lock。

    升级到写锁需要移除所有其他读锁(它们的选择事务完成)。但是如果另一个进程已经有了升级写锁的绝妙主意,那么你突然有两个进程在等待对方释放读锁,这样它们就可以获得写锁了。

    如果使用 select-for-update (UPDLOCK),那么它将从一开始就获得一个写锁,然后您就不会遇到死锁问题。

    【讨论】:

      【解决方案4】:

      单个查询之间的锁定可能发生在它们锁定单个行而不是整个表时:

      更新查询在表中的几行上获得更新锁,而选择查询在表中的其他一些行上获得读锁。然后,更新查询尝试在读锁定的行上获取更新锁,而选择查询尝试在更新锁定的行上获取读锁。

      使用升级锁可能会变得更加复杂,即数据库认为有太多单行被事务锁定,因此应该升级为锁定表的一部分或整个表。这意味着锁可能会影响不直接参与查询的行。

      【讨论】:

      • 读取和更新锁是兼容的。那么,这种情况怎么会发生呢?
      【解决方案5】:

      正确阅读事务和隔离级别:对于有些密集但相当彻底且技术中立的工作,请参阅Principles of Transaction Processing。它震撼了我的世界(让我头疼不已!)。

      我不确定您遇到了什么问题,或者您使用的是什么隔离级别。但是考虑一下:数据库引擎都知道,如果您在一个事务中进行读取,它如何判断您以后是否要进行写入?每当读取完成时,高隔离级别都需要锁定,可能在整个表上进行锁定以防止幻读,因为数据可能会影响以后的写入。

      您是否希望数据库等待任意长时间才能对您的数据进行排他锁?看看您的隔离级别,以及您是否将一系列读取作为隔离事务不必要地运行。不过,要确定你能忍受多脏的阅读并不总是那么容易……

      【讨论】:

      • 我认为发帖者的问题比对隔离级别的一般咆哮更具体。
      • 我不会将 PoTP 完全描述为咆哮。 Rob 在理解事务性方面特别寻求帮助,并且似乎在理解所涉及的权衡方面遇到了一些麻烦。如果指出有用的文献是在咆哮,那我可能一直在口吐白沫! YMMV。
      猜你喜欢
      • 1970-01-01
      • 2014-02-28
      • 2014-01-14
      • 2017-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      相关资源
      最近更新 更多