MySQL如何处理InnoDB并发事务中的间隙锁死锁

 更新时间:2023年10月15日 11:24:51   作者:jacheut  
这篇文章主要为大家介绍了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; 来查看锁的情况

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;

来查看死锁的情况。

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

总结

并发事务,间隙锁可能互斥

(1)A删除不存在的记录,获取共享间隙锁;

(2)B插入,必须获得排他间隙锁,故互斥;

  • 并发插入相同记录,可能死锁(某一个回滚)
  • 并发插入,可能出现间隙锁死锁(难排查)
  • show engine innodb status; 可以查看InnoDB的锁情况,也可以调试死锁

以上就是MySQL如何处理InnoDB并发事务中的间隙锁死锁的详细内容,更多关于MySQL InnoDB死锁的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:

相关文章

  • MySQL Limit性能优化及分页数据性能优化详解

    MySQL Limit性能优化及分页数据性能优化详解

    今天小编就为大家分享一篇关于MySQL Limit性能优化及分页数据性能优化详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • MySQL数据库中的安全设置方案

    MySQL数据库中的安全设置方案

    MySQL 是一个真正的多用户、多线程SQL数据库服务器,它是一个客户机/服务器结构的实现。MySQL是现在流行的关系数据库中其中的一种,相比其它的数据库管理系统(DBMS)来说,MySQL具有小巧、功能齐全、查询迅捷等优点。MySQL 主要目标是快速、健壮和易用。
    2015-04-04
  • 连接mysql错误问题解决方案

    连接mysql错误问题解决方案

    文章主要介绍了在Windows环境下,如何配置MySQL以允许外部机器连接,通过修改MySQL的配置文件,将root用户的访问权限从默认的localhost改为%,并执行flush操作,解决了连接错误的问题,感兴趣的朋友一起看看吧
    2025-02-02
  • mysql 8.0.21免安装版配置方法图文教程

    mysql 8.0.21免安装版配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.21免安装版配置教程,文中安装步骤介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • mysql下完整导出导入实现方法

    mysql下完整导出导入实现方法

    对于大量数据的导入导出,是件挺麻烦的事,需要考虑很多的细节,这类对于需要大量数据导入导出的朋友可以参考下。
    2010-12-12
  • 浅析MysQL B-Tree 索引

    浅析MysQL B-Tree 索引

    这篇文章主要介绍了MysQL B-Tree 索引的相关资料,帮助大家更好的理解和使用MySQL,感兴趣的朋友可以了解下
    2020-11-11
  • MySQL中定时器的底层实现原理及使用方法

    MySQL中定时器的底层实现原理及使用方法

    定时器可以用于定期执行特定的SQL语句、备份数据、生成报表等操作,本文将详细介绍MySQL中定时器的底层实现机制以及如何使用它
    2023-07-07
  • MySQL如何支撑起亿级流量

    MySQL如何支撑起亿级流量

    当每天新增数据上亿级的时候,单表数据量在百万级别,数据库服务器的高峰期写入压力、查询压力在都很高的时候,该如何让MySQL顺利支撑起来呢?本片文章将教给你详细的方案
    2021-09-09
  • mysql查询每小时数据和上小时数据的差值实现思路详解

    mysql查询每小时数据和上小时数据的差值实现思路详解

    这篇文章主要介绍了mysql查询每小时数据和上小时数据的差值,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • 深入了解MySQL中索引优化器的工作原理

    深入了解MySQL中索引优化器的工作原理

    本文将解读MySQL数据库查询优化器(CBO)的工作原理。文中简单介绍了MySQL Server的组成,MySQL优化器选择索引额原理以及SQL成本分析,需要的可以参考一下
    2022-11-11

最新评论