间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。

  最近用户反馈说系统老是出现insert时,等待超时了,最后发现是insert间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围。间隙锁的主要作用是为了防止出现幻读,但是它会把锁定范围扩大,有时候也会给我们带来麻烦,我们就遇到了。 在数据库参数中, 控制间隙锁的参数是:

  innodb_locks_unsafe_for_binlog,这个参数默认值是OFF, 也就是启用间隙锁, 他是一个bool值, 当值为true时表示disable间隙锁。

  那为了防止间隙锁是不是直接将innodb_locaks_unsafe_for_binlog设置为true就可以了呢? 不一定!而且这个参数会影响到主从复制及灾难恢复, 这个方法还尚待商量。

  间隙锁的出现主要集中在同一个事务中先delete后 insert的情况下, 当我们通过一个参数去删除一条记录的时候, 如果参数在数据库中存在,那么这个时候产生的是普通行锁,锁住这个记录, 然后删除, 然后释放锁。如果这条记录不存在,问题就来了, 数据库会扫描索引,发现这个记录不存在, 这个时候的delete语句获取到的就是一个间隙锁,然后数据库会向左扫描扫到第一个比给定参数小的值,向右扫描扫描到第一个比给定参数大的值, 然后以此为界,构建一个区间, 锁住整个区间内的数据, 一个特别容易出现死锁的间隙锁诞生了。

  举个例子:
  表testLock,有两个属性id,和name.有如下数据。

  开启一个会话: session 1

sql> set autocommit=0;                 ##取消自动提交
sql> delete from testLock where id = ‘6’;

  在开启一个会话: session 2

sql> set autocommit=0;##取消自动提交
sql> insert into testLock(id,name) values(‘6’,’hahaha’);

  在没有并发,或是极少并发的情况下, 这样会可能会正常执行,在Mysql中, 事务最终都是穿行执行, 但是在高并发的情况下, 执行的顺序就极有可能发生改变, 变成下面这个样子:

sql> delete from testLock where id = ‘6’;
sql> insert into testLock(id,name) values(‘6’, ‘hahaha’);

  这个时候最后一条语句:insert into testLock(id,name) values(‘6’, ‘hahaha’); 执行时就会爆出死锁错误。因为删除id = 6这条记录的时候,id为6之后的部分都被锁住了, 他们都取得了这一个数据段的共享锁, 所以在获取这个数据段的排它锁时出现死锁。

  这种问题的解决办法:通过修改数据库的参数innodb_locaks_unsafe_for_binlog来取消间隙锁从而达到避免这种情况的死锁的方式尚待商量, 那就只有修改代码逻辑, 存在才删除,尽量不去删除不存在的记录。

MySQL间隙锁问题的更多相关文章

  1. MySQL 间隙锁

    一.根据案例二:不同索引加锁顺序的问题,模拟重现死锁(详细操作步骤) 1.RR级别下,更新操作默认会加行级锁,行级锁会对索引加锁 2.如果更新语句使用多个索引,行级锁会先锁定普通索引,再锁定聚簇索引 ...

  2. mysql 间隙锁专题

    本文研究记录mysql间隙锁,涉及以下情况 唯一索引 非唯一索引 范围更新 等值更新 mysql8 mysql7 RR RC 数据准备 mysql> select * from vodb.tes ...

  3. Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)

    Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...

  4. 关于mysql 间隙锁

    前段时间系统老是出现update死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...

  5. mysql间隙锁

    什么是间隙锁(gap lock)? 间隙锁是一个在索引记录之间的间隙上的锁. 间隙锁的作用? 保证某个间隙内的数据在锁定情况下不会发生任何变化.比如我mysql默认隔离级别下的可重复读(RR). 当使 ...

  6. mysql间隙锁 转

    前面一文 mysql锁 介绍了mysql innodb存储引擎的各种锁,本文介绍一下innodb存储引擎的间隙锁,就以下问题展开讨论 1.什么是间隙锁?间隙锁是怎样产生的? 2.间隙锁有什么作用? 3 ...

  7. Mysql innodb 间隙锁

    前段时间系统老是出现insert死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...

  8. Mysql锁机制--间隙锁的危害

    Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 DROP TABLE IF EXISTS employee; CREATE TABLE IF NOT EXISTS ...

  9. Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

随机推荐

  1. @Value()读取配置文件属性,读出值为null的问题

    一.问题描述 自定义一个Filter如下: @Component public class JwtFilter extends GenericFilterBean{ @Value("${jw ...

  2. 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_10-webpack研究-安装nodejs

    1.3.2.1 安装Node.js webpack基于node.js运行,首先需要安装node.js. node -v:验证是否安装成功了.

  3. mac配置maven项目的方法(含导入selenium包)

    1.配置了java的环境变量    文件位置:  /Users/lucax/.bash_profile JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1 ...

  4. 程序间获取ALV显示数据(读取ALV GRID上的数据)

    程序间获取ALV数据的两种方法: 方法1:通过修改SUBMIT的目标程序,把内表EXPORT到内存,SUBMIT后IMPORT ,该方法需要修改目标程序,可以任意设置目标程序的中断点: * Execu ...

  5. php-fpm 重启

    查看php-fpm进程数:ps aux | grep -c php-fpm [root@ssy106c14c190c69 etc]# ps -ef | grep php-fpm ---  查看php- ...

  6. swift 第三课 宏定义 宏方法

    swift 与oc 不同,没有宏的定义就像 oc 可以这样写,直接调用: /* 默认颜色 */ #define RGBCOLOR_HEX(h) RGBCOLOR((((h)>>16)&am ...

  7. Jmeter 逻辑控制器 之 ForEach 控制器

    一.认识 ForEach 控制器 如下,创建一个 ForEach 控制器 设置界面如下: 输入变量前缀:要进行循环读取的变量前缀 Start index for loop (exclusive):循环 ...

  8. Vulnhub-XXE靶机学习

    ------------恢复内容开始------------ 前两天在微信公众号上看见了这个XXE靶场,就想试一试,虽然网上关于这个的文章已经写了太多太多了,但还是要写出来划划水,233333333, ...

  9. Linux 18.04 搭建lamp环境

    Linux 18.04 下搭建lamp环境 一.      安装服务器 a)     在配置好sources.list文件后,apt-get updata&upgrade更新软件: 二.    ...

  10. Unity-3D-H2

    1.简答题[建议做解释 游戏对象(GameObjects) 和 资源(Assets)的区别与联系. 游戏对象:直接出现在游戏的场景中,是资源整合的具体表现,对象通过层次结构来组织,通过整体-部分的关系 ...