死锁是指因每个事务都持有其它事务需要的锁,导致不同的事务无法继续执行的场景。因为每个事务都在等待资源可用,同时又不肯
释放自己持有的锁。
当多个事务对不同的表中的记录加锁(通过一些语句如UPDATE或SELECT ... FOR UPDATE),但是顺序相反时,可能产生死锁。
当此类语句锁定索引区间和间隙,但是因为不同的事务在不同的时间持有不同的锁,也可能发生死锁。
要想降低死锁概率,我们应该:是使用事务而不是 LOCK TABLES 语句;保证插入或更新语句所在事务是小事务,这样不会执行太长
时间;当多个不同的事务更新不同表中的记录或者更新区间记录数比较多时,每个事务中的操作顺序要相同;在SELECT ... FOR
UPDATE 和UPDATE ... WHERE语句使用的列上建立索引。隔离级别不会影响死锁概率,因为隔离级别影响读操作,但是死锁是在
写操作时才会发生。
在我们开启死锁检测后,发生死锁时,InnoDB引擎检测当时的状态,回滚其中一个事务。如果禁用了死锁检测,当发生死锁时,InnoDB
依靠innodb_lock_wait_timeout设置来回滚事务。因此,即使你的业务逻辑是正确的,你也一定要处理事务重试的场景。要查看InnoDB
用户事务中的最后一个死锁,可以使用SHOW ENGINE INNODB STATUS。如果因事务结构或者应用错误导致频繁发生死锁,可以开启
innodb_print_all_deadlocks来在mysql的错误日志中打印所有死锁信息。
15.7.5 死锁