MySQL记录锁、间隙锁、临键锁小案例演示
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。
有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章 一文详解MySQL的锁机制
这篇主要通过小案例来对记录锁、间隙(gap)锁、临键(next-key)锁做一个更好的理解。
这里先给出结论,再来用实际例子证明
1、当使用唯一索引来等值查询的语句时, 如果这行数据存在,不产生间隙锁,而是记录锁。
2、当使用唯一索引来等值查询的语句时, 如果这行数据不存在,会产生间隙锁。
3、当使用唯一索引来范围查询的语句时,对于满足查询条件但不存在的数据产生间隙(gap)锁,如果查询存在的记录就会产生记录锁,加在一起就是临键锁(next-key)锁。
4、当使用普通索引不管是锁住单条,还是多条记录,都会产生间隙锁;
5、在没有索引上不管是锁住单条,还是多条记录,都会产生表锁;
间隙锁会封锁该条记录相邻两个键之间的空白区域,防止其它事务在这个区域内插入、修改、删除数据,这是为了防止出现 幻读 现象;
间隙的范围?
根据检索条件向下寻找最靠近检索条件的记录值A作为左区间,向上寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B] 左开右闭。
接下来我们开始来验证以上结论
一、数据和环境准备
1、创建表和数据
CREATE TABLE `t` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`age` int NOT NULL COMMENT '年龄',
`mobile` int DEFAULT NULL COMMENT '手机号',
`name` varchar(8) DEFAULT NULL COMMENT '名称',
PRIMARY KEY (`id`),
KEY `index_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
id为主键(唯一索引)、age是普通索引、mobile没有加索引
同时插入数据如下。

在进行测试之前,我们先来看看t表中存在的隐藏间隙:

(-∞, 1]
(1, 4]
(4, 7]
(7, +supernum]
(其中supernum是数据库维护的最大的值。为了保证间隙锁都是左开右闭原则。)
2、关闭事务默认提交
mysql> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
结果显示,autocommit 的值是 ON,表示系统开启自动提交模式。
在 MySQL 中,可以使用 SET autocommit 语句设置事务的自动提交模式,语法格式如下:
SET autocommit = 0|1|ON|OFF;
对取值的说明:
值为 0 和值为 OFF:关闭事务自动提交。如果关闭自动提交,用户将会一直处于某个事务中,只有提交或回滚后才会结束当前事务,重新开始一个新事务。
值为 1 和值为 ON:开启事务自动提交。如果开启自动提交,则每执行一条 SQL 语句,事务都会提交一次。
二、唯一索引示例
1、等值查询且数据存在示例

事务A 等值查询id=4,因为id是主键,同时是等值查询存在该记录,所以只会在id=4这条记录上加记录锁,不会加间隙锁。
事务B 等值查询id=5,没有锁冲突,所以查询正常,不会堵塞。(如果事务B 等值查询id=4,因为事务A加了记录锁,所以会堵塞)
2、等值查询且数据不存在示例

事务A 等值查询id=5,因为查询记录不存在,所以无法加记录锁,但这里会存在一个(5,7]的间隙锁。
事务B 插入一条id=6的数据,因为上面存在了(5,7]的间隙锁,所以会堵塞。
3、范围查询示例

事务A 范围查询id>4,那么这里就会存在一个(4,+supernum]的临键(next-key)锁。
事务B 插入一条id=6的数据,因为上面存在了(4,+supernum]的临键(next-key)锁,所以会堵塞。
如果 事务B 是更新 id=7 的记录,同样会堵塞。
三、普通索引示例
1、等值查询值

事务A 等值查询age=4,因为age是普通索引,所以会产生临键(next-key)锁(1,4]和(4,7],左开右闭原则。
事务B 插入一个id=6、age=6的数据,因为age值在上面临键锁,范围内,所以也会堵塞。
2、左开右闭原则
按照上面的例子,如果事务B插入一条 id=6,age=1 的数据会不会堵塞呢,因为按照左开右闭原则,上面的age=1是开的,所以正常应该是可以插入的。
但实际上你真是实践之后,你发现同样也会堵塞。
通过实践之后,会发现,所谓的左开右闭原则,跟主键id有关系。
上面的事务A 等值查询age=4,它的当前主键id=4,上一条记录主键id=1,下条记录主键id=7。
如果插入 id<1, age 在(1,7)范围内,是 左闭右开原则。即age=1能插入,age=7会堵塞。
如果插入 1<id<7,age 在(1,7)范围内,是 左闭右闭原则。即age=1会堵塞,age=7也会堵塞。
如果插入 id>7,age 在(1,7)范围内,是 左开右闭原则。即age=1会堵塞,age=7能插入。
有关等值查询值不存在、普通索引范围的示例这里就不举了,跟上面的差不多,都会产生间隙锁。
四、无索引示例
1、等值查询值

事务A 等值查询 mobile = 8888884,因为mobile是无索引的,所以这个for update,变成表级排他(X)锁。
事务B 因为事务A已经加了表级的排他锁,所以其它事务无法进行任何的增删改操作。
2、范围查询

事务A 等值查询 mobile > 8888884,因为mobile是无索引的,所以这个for update,变成表级排他(X)锁。
事务B 因为事务A已经加了表级的排他锁,所以其它事务无法进行任何的增删改操作。
MySQL记录锁、间隙锁、临键锁小案例演示的更多相关文章
- 【Mysql】表锁 行锁 记录锁 间隙锁
Mysql中的锁 基于锁的属性分类:共享锁.排他锁. 基于锁的状态分类:意向共享锁.意向排它锁 根据锁的粒度分类:全局锁.页锁.表级锁.行锁(记录锁.间隙锁.和临键锁),实际上的锁就这些,上面两种分类 ...
- mysql 开发进阶篇系列 10 锁问题 (相同索引键值或同一行或间隙锁的冲突)
1.使用相同索引键值的冲突 由于mysql 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但如果是使用相同的索引键,是会出现锁冲突的.设计时要注意 例如:city表city_ ...
- mysql 锁问题 (相同索引键值或同一行或间隙锁的冲突)
1.使用相同索引键值的冲突 由于mysql 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但如果是使用相同的索引键,是会出现锁冲突的.设计时要注意 例如:city表city_ ...
- (10)MySQL进阶篇SQL优化(InnoDB锁-间隙锁)
1.概述 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录,叫做"间隙(GAP)&quo ...
- Mysql学习笔记-临键锁实验
前言 昨天同事跟我聊到一个问题:InnoDB里面间隙锁锁住的数据可以update么?我们经常都说间隙锁是InnoDB在RR隔离级别下防止幻读的一种处理手段.它可以防止数据在间隙范围中insert数据, ...
- (9)MySQL进阶篇SQL优化(InnoDB锁-记录锁)
1.概述 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点意味着:只有通过索引条件检索 ...
- MySQL数据库InnoDB存储引擎中的锁机制
MySQL数据库InnoDB存储引擎中的锁机制 http://www.uml.org.cn/sjjm/201205302.asp 00 – 基本概念 当并发事务同时访问一个资源的时候,有可能 ...
- MySQL性能调优——锁定机制与锁优化分析
针对多线程的并发访问,任何一个数据库都有其锁定机制,它的优劣直接关系着数据的一致完整性与数据库系统的高并发处理性能.锁定机制也因此成了各种数据库的核心技术之一.不同数据库存储引擎的锁定机制是不同的,本 ...
- MySQL学习(二)索引与锁 --- 2019年1月
1.Order By 是怎么工作的 MySQL做排序是一个成本比较高的操作.MySQL会为每个线程分配一个 sort_buffer 内存用于排序,该内存大小为 sort_buffer_size. 全字 ...
随机推荐
- 在Vs code中使用sftp插件以及连接windows远程sftp协议部署指导(解决vscode的sftp插件中文目录乱码问题)
一.启动SFtp 二.上手vs code SFTP插件 2.1 初始配置 2.2解决乱码问题 三.SFTP配置 3.1常用配置 3.2示例配置 四.SFTP使用 五.扩展阅读 一.启动SFtp 话说小 ...
- AtCoder Regular Contest 127
Portal B Description 给出\(n(\leq5\times10^4),L(\leq15)\),构造\(3n\)个不同\(L\)位的三进制数,使得在这\(3n\)个数的每一位上,0/1 ...
- 【JVM】JVM 概述、内存结构、溢出、调优(基础结构+StringTable+Unsafe+ByteBuffer)
什么是 JVM ? 定义 Java Virtual Machine - java 程序的运行环境(java 二进制字节码的运行环境) 好处 一次编写,到处运行 自动内存管理,垃圾回收功能 数组下标越界 ...
- 手把手教你汇编 Debug
关于汇编的第一篇文章: 爱了爱了,这篇寄存器讲的有点意思 Hello大家好,我是程序员cxuan!我们上篇文章了解了一下基本的寄存器,这篇文章我们来进行实际操作一下. 原文链接:手把手教你汇编 Deb ...
- [luogu5577]算力训练
(以下以$B$为进制,$m$为幂次,$n=B^{m}$) 定义$\oplus$为$k$进制下不进位加法,$\otimes$为$\oplus$卷积 令$f_{i,j}$表示前$i$个数的$\oplus$ ...
- [atARC101E]Ribbons on Tree
令$f(E')$表示强制$E'$中的边不被覆盖的方案数,根据容斥,$ans=\sum_{E'\subseteq E}(-1)^{|E'|}f(E')$ 对于给定的$E'$,$f(E')$即将$E'$中 ...
- Python3的运算符
比较运算符: == != < > <= >= 逻辑运算符 或与非 or and not x or y : x为true,则不计算y的值,直接返回ture x为false,则 ...
- Codeforces 891E - Lust(生成函数)
Codeforces 题面传送门 & 洛谷题面传送门 NaCly_Fish:<简单>的生成函数题 然鹅我连第一步都没 observe 出来 首先注意到如果我们按题意模拟那肯定是不方 ...
- Discontinuous Galerkin method for steady transport problem
下面讨论如何使用 Discontinuous Galerkin 求解恒定对流问题. 1.简介 恒定状态对流方程 \[\begin{equation} a\cdot \nabla \mathbf{u} ...
- 如何鉴定全基因组加倍事件(WGD)
目前鉴定全基因组加倍(whole-genome duplication events)有3种 通过染色体共线性(synteny) 方法是比较两个基因组的序列,并将同源序列的位置绘制成点状图,如果能在点 ...