翻译-InnoDB中的死锁(MySQL 5.7)
死锁指的是不同事务由于互相持有其他事务需要的锁而无法执行的场景。各自都需要等待资源释放,同事都不释放自己的锁资源。
补充:死锁的产生条件:1、资源互斥2、资源不可剥夺3、请求与保持4、循环等待
死锁可以发生在事务锁住了多个表的行(通过update或SELECT ... FOR UPDATE
),但是锁的时候的顺序是相反的。也可以发生在锁住的一个范围内的索引行或间隙,事务由于时间关系获取锁的数量不同。一个例子是:
https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlock-example.html
死锁不受隔离级别影响,因为隔离级别 只影响读取操作,而死锁发生在写入阶段。
如何减少死锁?
1、打开show engine innodb status 用于定位死锁
2、打开死锁日志
3、减少或避免长事务,
使事务的插入更新数据量尽量小,让事务尽快完成
4、不用select for update
5、事务内操作多个表的修改语句尽量放到一起,而不是到处放
不同事务更新时,更新表或数据行的顺序保持一致
6、索引要良好设计的,这样可以减少扫描到不需要的索引
7、序列化执行sql
当死锁被检测到,会回滚其中一个事务。如果死锁检测的开关是关了的,InnoDB依赖锁等待的超时时间来回滚。因此即使你的应用逻辑是正确的,你依然必须处理事务重试的场景。通过 SHOW ENGINE INNODB STATUS
查看上个死锁的事务。如果频繁发生死锁,可以将相关信息打印出来,启动
innodb_print_all_deadlocks
可以打印所以数据库死锁错误日志
https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks-handling.html