Documentation Home

15.7.5 InnoDB 中的死锁

死锁是不同的事务无法继续进行的情况,因为每个事务都持有另一个需要的锁。因为两个事务都在等待资源可用,所以都不会释放它持有的锁。

当事务锁定多个表中的行(通过 UPDATEor 之类的语句SELECT ... FOR UPDATE)但顺序相反时,可能会发生死锁。当这样的语句锁定索引记录和间隙的范围时,也会发生死锁,由于时间问题,每个事务都会获取一些锁而不是其他锁。有关死锁示例,请参阅 第 15.7.5.1 节,“InnoDB 死锁示例”

为了减少死锁的可能性,使用事务而不是LOCK TABLES语句;保持插入或更新数据的事务足够小,以至于它们不会长时间保持打开状态;SELECT ... FOR UPDATE当不同的事务更新多个表或大范围的行时,在每个事务中使用相同的操作顺序(例如 );SELECT ... FOR UPDATE在和 UPDATE ... WHERE 语句中使用的列上创建索引。死锁的可能性不受隔离级别的影响,因为隔离级别改变了读操作的行为,而死锁的发生是因为写操作。有关避免死锁情况和从死锁情况中恢复的详细信息,请参阅 第 15.7.5.3 节,“如何最小化和处理死锁”

当启用死锁检测(默认)并且确实发生死锁时,InnoDB检测条件并回滚其中一个事务(受害者)。如果使用 innodb_deadlock_detect变量禁用死锁检测, 则InnoDB依赖 innodb_lock_wait_timeout设置在出现死锁时回滚事务。因此,即使您的应用程序逻辑正确,您仍然必须处理必须重试事务的情况。InnoDB要查看用户事务 中的最后一个死锁,请使用SHOW ENGINE INNODB STATUS。如果频繁的死锁突出了事务结构或应用程序错误处理的问题,启用 innodb_print_all_deadlocks将有关所有死锁的信息打印到 mysqld错误日志。有关如何自动检测和处理死锁的更多信息,请参阅 第 15.7.5.2 节,“死锁检测”