MySQL8.0:死锁日志改进

MySQL8.0:死锁日志改进,第1张

为什么会出现这种情况?这是不是bug?

必须不是bug,我们来复现这一死锁场景

死锁逻辑:

session1 等待获取的锁 S Lock 阻塞了 session2 将要获取的锁,这在 MySQL8.0 中就会显示成 session1 持有的锁,同时也是 session1 等待的锁。就是这样。

本文死锁场景皆为工作中遇到(或同事遇到)并解决的死锁场景,写这篇文章的目的是整理和分享,欢迎指正和补充,本文死锁场景包括:

:以下场景隔离级别均为默认的Repeatable Read;

前提 :表 t_user 的 uid 字段创建了唯一索引,并拥有可更新字段age。

场景复现

相应业务案例和解决方案

该场景常见于事务中存在for循环更新某条记录的情况,死锁日志显示 lock_mode X locks rec but not gap waiting (即行锁而非间隙锁),解决方案:

表结构 :

场景复现

首先查询表中目前存在的记录:

执行两个事务的 *** 作:

死锁原因分析

解决方案

t_user结构改造为:

场景复现 *** 作(几率不高)

假设存在以下数据

死锁分析

事务1

锁住zone_id=1对应的间隙锁: zoneId in (1,2)

② 锁住索引zone_id=1对应的主键索引行锁id = [1,2]

③ 锁住uid=1对应的间隙锁: uid in (1, 2)

④ 锁住uid=1对应的主键索引行锁: id = [1, 3]

事务2

① 锁住zone_id=2对应的间隙锁: zoneId in (1,2)

② 锁住索引zone_id=2对应的主键索引行锁id = [3,4]

③ 锁住uid=2对应的间隙锁: uid in (1, 2)

④ 锁住uid=2对应的主键索引行锁: id = [2, 4]

解决方案 :创建联合索引,使执行计划只会用到一个索引。

测试表结构 :

场景复现 *** 作

解决办法:尽量避免这种插入又回滚的场景。

避免死锁的原则:


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/7507445.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-06
下一篇 2023-04-06

发表评论

登录后才能评论

评论列表(0条)

保存