0

我们经常得到错误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)

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

4

1 回答 1

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

    应该始终编写处理死锁的应用程序代码,并且通常的方法确实是简单地重试事务。如如何应对死锁中所述

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

    [ deletia ]

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

    [ deletia ]

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

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

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

  3. 假设死锁发生在插入表A中,死锁的原因是否是由于同一张表两次获得锁?

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

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

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

于 2013-05-21T07:39:18.810 回答