【问题标题】:Why do deadlocks happen in SQL Server?为什么 SQL Server 会发生死锁?
【发布时间】:2011-07-21 19:10:21
【问题描述】:

据我了解,SQL 死锁发生在 SPID 忙于处理另一个查询并且因为它现在很忙而无法运行另一个查询时。 SQL Server 从请求的资源中“随机”选择一个查询来死锁,然后失败,抛出异常。

我有一个运行大约 40 个实例的应用程序和一个后端 Windows 服务,所有这些都在访问同一个数据库。我希望减少死锁,以便增加可以同时运行的线程数。

  1. 为什么 SQL Server 不能将新查询排入队列并在有时间且资源可用时运行它?我正在做的大部分事情有时会等待几秒钟。
  2. 有没有一种方法可以全局设置事务隔离级别,而不必在每个新连接/会话开始时指定它?

【问题讨论】:

  • 您对deadlock 的定义不正确。通常 SQL Server 确实让其他请求等待。当它因为检测到死锁条件而终止查询时,是因为给定的一组查询无法完成(永远)并且必须有人输。我认为,如果您稍微了解一下什么是死锁,您将能够更好地从更好的问题中获得价值
  • “据我所知” ...该段的其余部分非常不正确。
  • 死锁与服务器太忙而无法处理请求无关。我建议你要么改写你的问题,要么去看看到底什么是死锁。
  • 你对死锁的理解是错误的,但我认为你有一个很好的问题。
  • lmao @heisenberg 会在 2011 年回到 HAM ......没关系 tsilb 我赞成你非常不正确的问题。我的意思是说真的,谁不知道什么是死锁? 谷歌搜索“什么是死锁”

标签: sql sql-server deadlock


【解决方案1】:

您对死锁的理解不正确。你所描述的是阻塞。将两者等同起来是一个常见的错误。

当两个独立的事务都需要不同的资源并且都不会释放它们拥有的一个以便另一个可以运行时,就会发生死锁。说明起来可能更容易:

SPID #1 获得资源 A 的锁定 SPID #2 获得资源 B 的锁定 SPID #1 现在需要锁定资源 B 才能完成 SPID #2 现在需要锁定资源 A 才能完成

SPID #1 无法完成(因此释放资源 A),因为 SPID #2 拥有它 SPID #2 无法完成(因此释放资源 B),因为 SPID #1 拥有它

由于两个 SPID 都无法完成,因此必须放弃(即被服务器选择为死锁受害者)并且会失败。

避免它们的最佳方法是使您的交易保持小(所需资源的数量)和快速。

【讨论】:

  • (+1) 想象一下两辆汽车在一条单车道上相向而行。他们都需要继续前行的道路,但显然他们都无法拥有它,除非一辆车倒车或消失(即rollback)。再多的等待、内存、磁盘等都无济于事
  • 有问题的 SPID 甚至没有运行正确的事务;仅限简单的 CRUD 语句。我必须在每一个上指定未提交吗?通常,我的应用程序将为每个语句/查询打开和关闭一个连接,除非它必须连续执行一堆。但是它们加起来超过了 n 个线程和 x 个用户。每个语句/查询(被死锁的)只需要大约 50-200 毫秒来执行。
  • @tsilb 您可能会发现这个aba_lockinfo 实用程序非常有用
  • SQL Server 中的@tslib 每个 CRUD 语句都在事务中运行。该事务可以是隐式的或显式的,但它始终存在。
  • @tsilb 这个问题比乍一看更复杂。正如 Tom H. 建议的那样,您可能想要搜索死锁以及“隔离级别”。非常简单地说,您不能告诉它不要对更改数据的命令进行锁定,但是您可以告诉它在读取操作时使用诸如“With NOLOCK”查询提示之类的东西来读取锁定。但这会带来风险,应该非常小心地使用。
【解决方案2】:

死锁是两个处理线程都被另一个阻塞的地方(它可以更多,但两个足够复杂)。因此,一个线程锁定了一张表,然后请求锁定另一张表。另一个表被第二个线程锁定,由于它正在等待第一个表上的锁定,因此无法继续进行。

其中一个必须被丢弃的原因是,在死锁中,它们永远不会结束——两个线程都无法前进。唯一的答案是停止一个以让另一个完成。

在您所说的那种情况下减少死锁的解决方案可能是重新设计解决方案。如果你能确保更少的锁定发生,你就会有更少的死锁。

【讨论】:

    【解决方案3】:

    发生死锁是因为,两个并发事务可能会重叠并锁定不同的资源,这两个事务都需要另一个事务才能完成。

    让我们想象一下: 1 - 事务 A 锁定 row1 2 - 事务 B 锁定 row2 3 - 事务 A 尝试锁定 row1,并且由于之前的锁定,SQL Server 等待 4 - 事务 B 尝试锁定 row2,并且由于之前的锁定,SQL Server 等待

    因此,SQL Server 必须选择事务,将其终止,并允许另一个继续。

    这张图片很好地说明了这种情况:http://www.eupodiatamatando.com/wp-content/uploads/2008/01/deadlocknajkcomafarialibh3.jpg

    【讨论】:

      猜你喜欢
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多