死锁是不同的事务无法继续进行的情况,因为每个事务都持有另一个需要的锁。因为两个事务都在等待资源可用,所以都不会释放它持有的锁。
当事务锁定多个表中的行(通过
UPDATE
or
之类的语句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 节,“死锁检测”。