死锁是指不同的事务无法继续执行,因为每个事务都持有锁,而其他事务需要该锁。由于每个事务都在等待资源可用,因此它们永远不会释放锁。
死锁可能发生在事务锁定多个表中的行(通过语句如 UPDATE
或 SELECT ... FOR UPDATE
),但顺序相反。死锁也可能发生在锁定索引记录和间隙的范围时,每个事务获取一些锁,但由于计时问题而没有获取其他锁。有关死锁示例,请参见 第 17.7.5.1 节,“InnoDB 死锁示例”。
为了减少死锁的可能性,请使用事务而不是 LOCK TABLES
语句;保持事务小,以便它们不需要长时间保持打开状态;当不同的事务更新多个表或大量行时,请在每个事务中使用相同的操作顺序(例如 SELECT ... FOR UPDATE
);在 SELECT ... FOR UPDATE
和 UPDATE ... WHERE
语句中使用的列上创建索引。死锁的可能性不受隔离级别的影响,因为隔离级别改变读操作的行为,而死锁是由于写操作引起的。有关避免和恢复死锁条件的更多信息,请参见 第 17.7.5.3 节,“如何最小化和处理死锁”。
当启用死锁检测(默认)且发生死锁时,InnoDB
会检测该条件并回滚其中一个事务(受害者)。如果禁用死锁检测使用 innodb_deadlock_detect
变量,InnoDB
将依赖 innodb_lock_wait_timeout
设置来回滚事务以避免死锁。因此,即使您的应用程序逻辑正确,您仍需要处理事务重试的情况。要查看最后一个死锁的 InnoDB
用户事务,请使用 SHOW ENGINE INNODB STATUS
。如果频繁的死锁突出了事务结构或应用程序错误处理问题,请启用 innodb_print_all_deadlocks
以将所有死锁信息打印到 mysqld 错误日志中。有关死锁自动检测和处理的更多信息,请参见 第 17.7.5.2 节,“死锁检测”。