原文
[TOC]
死锁是两个不同的事务无法进行的一种情况,因为它们互相持有另一方需要的锁,它们都等待资源可用,但却没有任何一方主动释放自己持有的锁。
多个事务在多个表中使用行锁(通过 UPDATE 或 SELECT ... FOR UPDATE)可能会导致死锁,在一些语句索引记录的锁范围中,每个事务都会获取锁但由于时序问题不会都获取到锁,此时也会产生死锁。参见例子:Section 15.5.5.1, “An InnoDB Deadlock Example”.
为了减少死锁发生的可能,应该使用事务,而不是 LOCK TABLES语句;使插入和更新数据的事务足够小,以保证它们不会开启很长时间;当不同的事务需要更新多个表或大量行时,在每个事务中使用相同的操作序列(例如: SELECT ... FOR UPDATE);为在像 SELECT ... FOR UPDATE 和 UPDATE ... WHERE 之类的语句中使用的字段创建索引,事务隔离级别不会影响死锁的发生的可能,因为事务隔离级别影响的是读操作的行为,而导致死锁发生的是写操作。了解更多避免死锁和从死锁状态恢复的信息,可参见Section 15.5.5.3, “How to Minimize and Handle Deadlocks”.
当死锁监测开启(默认)并有死锁发生时,InnoDB会察觉到并回滚其中的一个事务(被死锁影响的事务)。如果通过 innodb_deadlock_detect 配置项禁用死锁监测,在死锁发生时,InnoDB依赖innodb_lock_wait_timeout设置来回滚事务。所以,即使你的应用逻辑是正确的,在事务重试时你也必须对这种情况做处理。在InnoDB中可以使用SHOW ENGINE INNODB STATUS查看最后的死锁。如果死锁经常发生影响事务结构和应用,可以通过 innodb_print_all_deadlocks 开启配置将所有死锁日志打印出来。更多关于死锁的发生和处理可参见:Section 15.5.5.2, “Deadlock Detection and Rollback”
Read More