难点描述: 在 InnoDB 引擎的可重复读(RR)隔离级别下,并没有并发修改同一行数据,仅仅是范围查询或插入操作,却频繁报出 Deadlock found when trying to get lock 异常。
原理: 为了解决“幻读”问题,InnoDB 引入了 Next-Key Lock(临键锁 = 记录锁 + 间隙锁)。
当执行 SELECT ... FOR UPDATE 或 UPDATE ... WHERE id > 10 时,MySQL 不仅锁住存在的记录,还会锁住“间隙”。
死锁场景: 事务 A 获取了间隙锁,事务 B 也获取了同一个范围的间隙锁(间隙锁之间不冲突)。随后,事务 A 和 事务 B 都试图向这个间隙中 INSERT 数据,都会被对方的间隙锁阻塞,从而形成死锁。
解决方案:
降低隔离级别: 如果业务允许,将隔离级别降为 Read Committed (RC),RC 级别下没有间隙锁(需注意 Binlog 格式设为 ROW)。
优化索引: 尽量使用唯一索引进行等值查询,避免范围锁定。
日志分析: 开启 innodb_print_all_deadlocks,通过分析死锁日志确定锁冲突的源头。


评论