文档首页
MySQL 8.4 参考手册
8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 100%

17.7.5 InnoDB 中的死锁17.7.5 Deadlocks in InnoDB

死锁是一种情况,在这种情况下,多个事务无法继续进行,因为每个事务都持有另一个事务所需的锁。由于所有涉及的事务都在等待同一资源变得可用,所以它们没有一个会释放自己持有的锁。A deadlock is a situation in which multiple transactions are unable to proceed because each transaction holds a lock that is needed by another one. Because all transactions involved are waiting for the same resource to become available, none of them ever releases the lock it holds.

当事务以相反的顺序锁定多个表中的行(通过诸如 UPDATE 或 SELECT ... FOR UPDATE 等语句)时,可能会发生死锁。当这些语句锁定索引记录和间隙的范围时,也可能发生死锁,每个事务由于时间问题而获取了一些锁但没有获取其他锁。有关死锁示例,请参见 第 17.7.5.1 节,“一个 InnoDB 死锁示例”。A deadlock can occur when transactions lock rows in multiple tables (through statements such as UPDATE or SELECT ... FOR UPDATE), but in the opposite order. A deadlock can also occur when such statements lock ranges of index records and gaps, with each transaction acquiring some locks but not others due to a timing issue. For a deadlock example, see Section 17.7.5.1, “An InnoDB Deadlock Example”.

为了减少死锁的可能性,应使用事务而不是LOCK TABLES语句;保持插入或更新数据的事务尽可能小,以免长时间保持开启;当不同事务更新多个表或大量行时,在每个事务中使用相同的操作顺序(例如SELECT ... FOR UPDATE);在用于SELECT ... FOR UPDATE和UPDATE ... WHERE语句的列上创建索引。死锁的可能性不会受隔离级别影响,因为隔离级别改变的是读操作的行为,而死锁发生是由于写操作。有关避免和恢复死锁条件的更多信息,请参见第 17.7.5.3 节,“如何最小化和处理死锁”。To reduce the possibility of deadlocks, use transactions rather than LOCK TABLES statements; keep transactions that insert or update data small enough that they do not stay open for long periods of time; when different transactions update multiple tables or large ranges of rows, use the same order of operations (such as SELECT ... FOR UPDATE) in each transaction; create indexes on the columns used in SELECT ... FOR UPDATE and UPDATE ... WHERE statements. The possibility of deadlocks is not affected by the isolation level, because the isolation level changes the behavior of read operations, while deadlocks occur because of write operations. For more information about avoiding and recovering from deadlock conditions, see Section 17.7.5.3, “How to Minimize and Handle Deadlocks”.

当启用死锁检测(默认设置)并且确实发生死锁时,InnoDB 会检测到该情况并回滚其中一个事务(受害者)。如果使用 innodb_deadlock_detect 变量禁用死锁检测,InnoDB 将依赖 innodb_lock_wait_timeout 设置在发生死锁时回滚事务。因此,即使你的应用逻辑是正确的,你仍然必须处理事务需要重试的情况。要查看 InnoDB 用户事务中的最后一次死锁,请使用 SHOW ENGINE INNODB STATUS。如果频繁的死锁显示事务结构或应用错误处理存在问题,请启用 innodb_print_all_deadlocks,将所有死锁信息打印到 mysqld 错误日志中。有关死锁如何自动检测和处理的更多信息,请参见 第 17.7.5.2 节,“死锁检测”。When deadlock detection is enabled (the default) and a deadlock does occur, InnoDB detects the condition and rolls back one of the transactions (the victim). If deadlock detection is disabled using the innodb_deadlock_detect variable, InnoDB relies on the innodb_lock_wait_timeout setting to roll back transactions in case of a deadlock. Thus, even if your application logic is correct, you must still handle the case where a transaction must be retried. To view the last deadlock in an InnoDB user transaction, use SHOW ENGINE INNODB STATUS. If frequent deadlocks highlight a problem with transaction structure or application error handling, enable innodb_print_all_deadlocks to print information about all deadlocks to the mysqld error log. For more information about how deadlocks are automatically detected and handled, see Section 17.7.5.2, “Deadlock Detection”.