【问题标题】:To what extend is table design responsible for the occurrence of deadlocks?表设计在多大程度上对死锁的发生负责?
【发布时间】:2013-05-21 15:39:18
【问题描述】:

我们经常收到错误SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction。一些网站通过简单地使用 try/catch 重试来显示解决方案,例如 MySQL Deadlock Detection via PHP。 我现在的问题是;表设计在多大程度上导致了这种死锁的发生?特别是我对以下示例感兴趣。

Table A
  - id (int, primary key)
  - a  (int, foreign key -- references B.a)
  - b  (int, foreign key -- also references B.a)
Table B
  - id (int, primary key)
  - type (enum)
  - a  (int)

A 中的记录可能包含A.aA.b 的值,这两个值可能引用也可能不引用表B 中的相同记录。假设死锁发生在表 A 中的一次插入操作中,死锁的原因是否是由于同一张表两次获得了锁?如果我们根据type 的值将表B 拆分为表B 和表B',死锁的数量会减少吗?在您的回答中,请不要争论糟糕的设计。

【问题讨论】:

    标签: mysql database-deadlocks


    【解决方案1】:
    1. 一些网站通过简单地使用 try/catch 重试来显示解决方案

      应该总是编写处理死锁的应用程序代码,通常的方法确实是简单地重试事务。如How to Cope with Deadlocks 中所述:

      Deadlocks 是事务数据库中的一个经典问题,但它们并不危险,除非它们太频繁以至于您根本无法运行某些事务。通常,您必须编写应用程序,以便它们随时准备好在事务因死锁而回滚时重新发出事务。

      [ <strong><em>deletia</em></strong> ]

      您可以使用以下技术应对死锁并降低其发生的可能性:

      [ <strong><em>deletia</em></strong> ]

      • 如果由于死锁而失败,请随时准备重新发出事务。死锁并不危险。请再试一次。
    2. 表设计在多大程度上导致了这种死锁的发生?

      表设计当然是一个促成因素,但我很少会因为死锁而主动改造我的架构(除非引入适当的索引,如果它们不存在)。当然,这不会是我的第一个补救措施。

      相反,过多的死锁通常可以在一个应用程序代码中解决:通过确保有罪的事务以一致的顺序获取锁;通过减少事务的大小,以便尽快提交它们并释放它们的锁;或通过使用较低的隔离级别。如果做不到这一点,人们总是可以序列化自己的交易。

    3. 假设死锁发生在表A的insert上,死锁的原因会不会是同一张表两次获取锁造成的?

      否:锁由 session 持有;一旦会话持有一个锁,它就不需要重新获取它。

    4. 如果我们根据类型的值将表B分成表B和表B',死锁的数量会更少吗?

      我想不出任何理由单独进行这样的重新设计会减少死锁,尽管它可能增加死锁(总体上需要更多记录,需要更多锁)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 2019-07-02
      • 2012-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多