MySQL InnoDB调试死锁

前提

1、在RR隔离级别下。
2、查看间隙锁是否关闭
区间锁(间隙锁,临键锁)是InnoDB特有施加在索引记录区间的锁,MySQL5.6可以手动关闭区间锁,它由innodb_locks_unsafe_for_binlog参数控制:

  • 设置为ON,表示关闭区间锁,此时一致性会被破坏(所以是unsafe)
  • 设置为OFF,表示开启区间锁

show global variables like “innodb_locks%”;

3、show global variables like “autocommit”; 查看事务是否自动提交。

数据准备

InnoDB的行锁都是实现在索引上的,实验可以使用主键,建表时设定为innodb引擎:

create table t (
id int(10) primary key
)engine=innodb;

-- 插入一些实验数据:
start transaction;
insert into t values(1);
insert into t values(3);
insert into t values(10);
commit;

这是实验的初始状态,不同实验开始之初,都默认回到初始状态。

实验一、间隙锁互斥

开启区间锁,RR的隔离级别下,上例会有:
(-infinity, 1)
(1, 3)
(3, 10)
(10, infinity)
这四个区间。

事务A删除某个区间内的一条不存在记录,获取到共享间隙锁,会阻止其他事务B在相应的区间插入数据,因为插入需要获取排他间隙锁。

-- session A:
set session autocommit=0;
start transaction;
delete from t where id=5;

-- session B:
set session autocommit=0;
start transaction;
insert into t values(0);
insert into t values(2);
insert into t values(12);
insert into t values(7);

事务B插入的值:0, 2, 12都不在(3, 10)区间内,能够成功插入,而7在(3, 10)这个区间内,会阻塞。

可以使用:show engine innodb status; 来查看锁的情况。

MySQL InnoDB调试死锁

insert into t values(7); 正在等待共享间隙锁的释放。

如果事务A提交或者回滚,事务B就能够获得相应的锁,以继续执行。

如果事务A一直不提交,事务B会一直等待,直到超时,超时后会显示:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

实验二、共享排他锁死锁

回到数据的初始状态,这次需要三个并发的session。

-- session A先执行:
set session autocommit=0;
start transaction;
insert into t values(7);
 
-- session B后执行:
set session autocommit=0;
start transaction;
insert into t values(7);
 
-- session C最后执行:
set session autocommit=0;
start transaction;
insert into t values(7);

三个事务都试图往表中插入一条为7的记录:
(1)A先执行,插入成功,并获取id=7的排他锁;
(2)B后执行,需要进行PK校验,故需要先获取id=7的共享锁,阻塞;
(3)C后执行,也需要进行PK校验,也要先获取id=7的共享锁,也阻塞;

如果此时,session A执行:
rollback;
id=7排他锁释放。

则B,C会继续进行主键校验:
(1)B会获取到id=7共享锁,主键未互斥;
(2)C也会获取到id=7共享锁,主键未互斥;

B和C要想插入成功,必须获得id=7的排他锁,但由于双方都已经获取到id=7的共享锁,它们都无法获取到彼此的排他锁,死锁就出现了。

当然,InnoDB有死锁检测机制,B和C中的一个事务会插入成功,另一个事务会自动放弃:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

实验三、并发间隙锁的死锁

共享排他锁,在并发量插入相同记录的情况下会出现,相应的案例比较容易分析。而并发的间隙锁死锁,是比较难定位的。

回到数据的初始状态,这次需要两个并发的session,其SQL执行序列如下:

A:set session autocommit=0;
A:start transaction;
A:delete from t where id=6;
         B:set session autocommit=0;
         B:start transaction;
         B:delete from t where id=7;
A:insert into t values(5);
         B:insert into t values(8);

A执行delete后,会获得(3, 10)的共享间隙锁。
B执行delete后,也会获得(3, 10)的共享间隙锁。
A执行insert后,希望获得(3, 10)的排他间隙锁,于是会阻塞。
B执行insert后,也希望获得(3, 10)的排他间隙锁,于是死锁出现。

仍然使用:
show engine innodb status;
来查看死锁的情况。

MySQL InnoDB调试死锁

另外,检测到死锁后,事务2自动回滚了:WE ROLL BACK TRANSACTION (2)
事务1将会执行成功。

总结

  • 并发事务,间隙锁可能互斥
    (1)A删除不存在的记录,获取共享间隙锁;
    (2)B插入,必须获得排他间隙锁,故互斥;
  • 并发插入相同记录,可能死锁(某一个回滚)
  • 并发插入,可能出现间隙锁死锁(难排查)
  • show engine innodb status; 可以查看InnoDB的锁情况,也可以调试死锁

文章来源:https://www.cnaaa.net,转载请注明出处:https://www.cnaaa.net/archives/9886

(0)
凯影的头像凯影
上一篇 2023年10月23日 下午5:18
下一篇 2023年10月24日 下午5:15

相关推荐

  • MySQL 如何查找删除重复行?

    如何查找重复行 第一步是定义什么样的行才是重复行。多数情况下很简单:它们某一列具有相同的值。本文采用这一定义,或许你对“重复”的定义比这复杂,你需要对sql做些修改。本文要用到的数据样本: 前面两行在day字段具有相同的值,因此如何我将他们当做重复行,这里有一查询语句可以查找。查询语句使用GROUP BY子句把具有相同字段值的行归为一组,然后计算组的大小。 …

    2023年4月25日
    1.2K00
  • count(1)、count(*)与count(列名)的执行区别

    在工作中遇到count(*)、count(1)、count(col) ,可能会让你分不清楚,都是计数,干嘛这么搞这么多东西。 count 作用 COUNT(expression):返回查询的记录总数,expression 参数是一个字段或者 * 号。 测试 MySQL版本:5.7.29 创建一张用户表,并插入一百万条数据,其中gender字段有五十万行是为n…

    2023年1月12日
    1.8K00
  • Mysql报错:1030, ‘Got error 28 from storage engine‘的解决方法(附相关解决脚本)

    问题 客户反应过来网站打开是出现错误,错误现象如下: 尝试登录phpMyadmin链接,显示如下错误 连接数据库相关表格显示以下错误 解决方法 经过判断,是服务器系统盘满了 找到我们的脚本,运行后清理c盘(https://www.cnaaa.net/archives/4743) 还可以设置一个定时任务,定期清理,防止再遇到这种问题,打开”计算机管理“,找到“…

    2022年6月15日
    2.0K00
  • Oracle用户密码过期的处理方法

    受影响版本:Oracle11g以上版本。 导致密码消失的原因:Oracle 11g中默认的DEFAULT概要文件中口令有效期PASSWORD_LIFE_TIME默认值为180天。 当以客户端登陆Oracle提示ORA-28002,则基本可以确定登陆帐号已过有效期,使用具有DBA权限的帐号重置该帐号密码即可。 解决方法: 以下步骤以具有DBA权限用户操作 1.…

    2024年5月9日
    1.9K00
  • MYSQL分区

    一:概念 MySQL从5.1版本开始支持分区的功能。分区是指根据一定的规则,数据库把一个表分解成多个更小的、更容易管理的部分。就访问数据库的应用而言,逻辑上只有一个表或一个索引,但是实际上这个表可能由数10个物理分区对象组成,每个分区都是一个独立的对象,可以独自处理,可以作为表的一部分进行处理。分区对应用来说是完全透明的,不影响应用的业务逻辑。 二:分区优点…

    2024年6月3日
    1.6K00

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

在线咨询: QQ交谈

邮件:712342017@qq.com

工作时间:周一至周五,8:30-17:30,节假日休息

关注微信