死锁是一种因为每个事务都持有另一个需要的锁,导致不同事务无法继续进行的情况。因为两个事务都在等待资源变得可用,所以它们都不会释放它持有的锁。
当事务锁定多个表中的行(通过诸如 UPDATE或SELECT ... FOR UPDATE之类的语句)但顺序相反时,可能会发生死锁。当此类语句锁定索引记录和间隙的范围时,也可能发生死锁。每个事务由于时间问题而获得一些锁,但无法获得其他锁。
为了减少死锁的可能性,请使用事务而不是LOCK TABLES语句;保持插入或更新数据的事务足够小,以使其不会长时间保持打开状态;当不同事务更新多个表或大范围的行时,在每个事务中使用相同的操作顺序;在SELECT ... FOR UPDATE和 UPDATE ... WHERE 语句中使用的列上创建索引。死锁的可能性不受隔离级别的影响,因为隔离级别改变了读操作的行为,而死锁是因为写操作而发生的。
当启用死锁检测(默认)并且确实发生死锁时,InnoDB会检测死锁情况并回滚其中一个事务。如果使用innodb_deadlock_detect变量禁用死锁检测,则在发生死锁时InnoDB依赖innodb_lock_wait_timeout设置回滚事务。因此,即使您的应用程序逻辑是正确的,您仍然必须处理必须重试事务的情况。InnoDB要查看用户事务中的最后一个死锁,请使用SHOW ENGINE INNODB STATUS。如果频繁的死锁突出了事务结构或应用程序错误处理的问题,启用innodb_print_all_deadlocks将有关所有死锁的信息打印到mysqld错误日志。