14.7.5 InnoDB 中的死锁

死锁是指由于每个事务都持有对方需要的锁而无法进行其他事务的情况。因为这两个事务都在 await 资源变得可用,所以两个都不会释放它持有的锁。

当事务锁定多个 table 中的行时(通过诸如UPDATE选择...更新的语句),但 Sequences 相反,则会发生死锁。当此类语句锁定索引记录和间隙的范围时,由于时序问题,每个事务都获得了一些锁而没有获得其他锁,也会发生死锁。有关死锁的示例,请参见第 14.7.5.1 节“ InnoDB 死锁示例”

为了减少死锁的可能性,请使用事务而不是LOCK TABLES语句;保持插入或更新数据的事务足够小,以使其长时间不保持打开状态;当不同的事务更新多个 table 或大范围的行时,在每个事务中使用相同的操作 Sequences(例如选择...更新);在选择...更新更新...在哪里语句中使用的列上创建索引。死锁的可能性不受隔离级别的影响,因为隔离级别更改了读取操作的行为,而死锁则由于写入操作而发生。有关避免死锁状态并从死锁状态中恢复的更多信息,请参见第 14.7.5.3 节“如何最小化和处理死锁”

如果启用了死锁检测(默认设置)并且确实发生了死锁,则InnoDB检测到该情况并回滚其中一个事务(受害方)。如果使用innodb_deadlock_detect配置选项禁用了死锁检测,则InnoDB将依靠innodb_lock_wait_timeout设置在发生死锁的情况下回滚事务。因此,即使您的应用程序逻辑正确,您仍必须处理必须重试事务的情况。要查看InnoDB用户事务中的最后一个死锁,请使用显示引擎的 INNODB 状态命令。如果频繁的死锁凸显了事务结构或应用程序错误处理方面的问题,请在启用innodb_print_all_deadlocks设置的情况下运行,以将有关所有死锁的信息打印到mysqld错误日志中。有关如何自动检测和处理死锁的更多信息,请参见第 14.7.5.2 节“死锁检测和回滚”