mysql间隙锁
什么是间隙锁(gap lock)?
间隙锁是一个在索引记录之间的间隙上的锁。
间隙锁的作用?
保证某个间隙内的数据在锁定情况下不会发生任何变化。比如我mysql默认隔离级别下的可重复读(RR)。
当使用唯一索引来搜索唯一行的语句时,不需要间隙锁定。如下面语句的id列有唯一索引,此时只会对id值为10的行使用记录锁。
select * from t where id = 10 for update;// 注意:普通查询是快照读,不需要加锁
如果,上面语句中id列没有建立索引或者是非唯一索引时,则语句会产生间隙锁。
如果,搜索条件里有多个查询条件(即使每个列都有唯一索引),也是会有间隙锁的。
需要注意的是,当id列上没有索引时,SQL会走聚簇索引的全表扫描进行过滤,由于过滤是在MySQL Server层面进行的。因此每条记录(无论是否满足条件)都会被加上X锁。但是,为了效率考量,MySQL做了优化,对于不满足条件的记录,会在判断后放 锁,最终持有的,是满足条件的记录上的锁。但是不满足条件的记录上的加锁/放锁动作是不会省略的。所以在没有索引时,不满足条件的数据行会有加锁又放锁的耗时过程。
间隙的范围?
根据检索条件向下寻找最靠近检索条件的记录值A作为左区间,向上寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B] 左开右闭。
通过上面的描述,感觉很抽象?
没关系,下面我们来通过具体的实验来说明gap锁。再次强调(当使用唯一索引来搜索唯一行的语句时,不需要间隙锁定)
我们先创建一张数据表:
MariaDB [locktest]> create table gaplockt(
-> id int not null,
-> name varchar(255) not null primary key,
-> key `id_index` (`id`)
-> );
在向表中插入一些数据:
MariaDB [locktest]> insert into gaplockt values(1,'panchao'),(5,'songzuer'),(10,
'yangmi');
现在我们的表情况是这样的:
MariaDB [locktest]> select * from gaplockt;
+----+----------+
| id | name |
+----+----------+
| 1 | panchao |
| 5 | songzuer |
| 10 | yangmi |
+----+----------+
接下来我们设置autocommit = 0;
MariaDB [locktest]> set autocommit = 0;
MariaDB [locktest]> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
现在我们的准备工作已经做完了,我们再事物A中给记录添加一个写锁:
MariaDB [locktest]> select * from gaplockt where id = 5 for update;
+----+----------+
| id | name |
+----+----------+
| 5 | songzuer |
+----+----------+
由于id不是唯一索引,表上加上相应的gap锁。如下图:
以上语句会给表加上的gap锁包括(gap2和gap3),也就是1~5U5~10,特别注意这个区间为左开右闭区间(1,10],没理解没关系,我们接下来通过实验来验证。
实验1、
MariaDB [locktest]> insert into gaplockt values(6,'jingruyang');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [locktest]> insert into gaplockt values(4,'jingruyang');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [locktest]> insert into gaplockt values(1,'jingruyang');
Query OK, 1 row affected (0.00 sec)
MariaDB [locktest]> insert into gaplockt values(10,'jingruyang10');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
通过以上实验,我们可以看到当id = 1的时候,我们是能添加数据的,但是当id = 10的时候我们是不能添加数据的,事实证明,我们的这个gap锁区间为(1,10]
实验2、
接下来我们来讨论gap1和gap4的问题。
当我们执行以下语句的时候,或收获gap4锁。
MariaDB [locktest]> select * from gaplockt where id = 100 for update;
那么gap4锁的范围是多少呢? 是(10,100]吗?
直接告诉你们答案,不是,它的范围是(10,+∞),下面我们通过实验来验证。
MariaDB [locktest]> insert into gaplockt values(99,'jingruyang99');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [locktest]> insert into gaplockt values(100,'jingruyang100');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [locktest]> insert into gaplockt values(1000,'jingruyang1000');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
可以看到id=99 id= 100 id=1000 都是上了锁的,所以gap4的区间为(10,+∞)
我们再来讨论gap1
执行以下语句获取gap1
MariaDB [locktest]> select * from gaplockt where id = -100 for update;
gap1的区间我直接告诉大家,(-∞,1)
下面我们通过实验证明。
MariaDB [locktest]> insert into gaplockt values(-99,'jingruyang99');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [locktest]> insert into gaplockt values(-100,'jingruyang99');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [locktest]> insert into gaplockt values(-10000,'jingruyang99');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
看到上面的结果,就不用我多说什么了吧。
以下是两个比较有参考价值的链接,有兴趣的朋友可以看一下。
mysql间隙锁的更多相关文章
- MySQL 间隙锁
一.根据案例二:不同索引加锁顺序的问题,模拟重现死锁(详细操作步骤) 1.RR级别下,更新操作默认会加行级锁,行级锁会对索引加锁 2.如果更新语句使用多个索引,行级锁会先锁定普通索引,再锁定聚簇索引 ...
- mysql 间隙锁专题
本文研究记录mysql间隙锁,涉及以下情况 唯一索引 非唯一索引 范围更新 等值更新 mysql8 mysql7 RR RC 数据准备 mysql> select * from vodb.tes ...
- Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...
- 关于mysql 间隙锁
前段时间系统老是出现update死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...
- MySQL间隙锁问题
间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间. 最近用户反馈说系统老是出现insert时,等待超时了,最后发现是ins ...
- mysql间隙锁 转
前面一文 mysql锁 介绍了mysql innodb存储引擎的各种锁,本文介绍一下innodb存储引擎的间隙锁,就以下问题展开讨论 1.什么是间隙锁?间隙锁是怎样产生的? 2.间隙锁有什么作用? 3 ...
- Mysql innodb 间隙锁
前段时间系统老是出现insert死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...
- Mysql锁机制--间隙锁的危害
Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 DROP TABLE IF EXISTS employee; CREATE TABLE IF NOT EXISTS ...
- Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
随机推荐
- matlab实现梯度下降法(Gradient Descent)的一个例子
在此记录使用matlab作梯度下降法(GD)求函数极值的一个例子: 问题设定: 1. 我们有一个$n$个数据点,每个数据点是一个$d$维的向量,向量组成一个data矩阵$\mathbf{X}\in \ ...
- EPLAN文本输入怎么转行,路径功能文本换行方法
EPLAN文本输入怎么转行,路径功能文本换行方法 在输入文本时,按CTRL+ENTER可以将字体换行 Ctrl+回车键
- Netty中的这些知识点,你需要知道!
一.Channel Channel是一个接口,而且是一个很大的接口,我们称之为“大而全”,囊括了server端及client端接口所需要的接口. Channel是一个门面,封装了包括网络I/O及相关的 ...
- WeChair——团队展示
这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 团队名称 WeChair 这个作业要求在哪里 团队作业第一次 这个作业的目标 团队合作,项目开发 作业正文 如下 其他参考文献 ...
- Android studio debug apk包安装失败
可在根目录gradle.properties中配置 android.injected.testOnly=false
- jquery 李南江老师jquery和ajax视频教程
链接:https://pan.baidu.com/s/11QF97RLg1aW9bf6o-CdHvQ 密码:qfer https://www.bilibili.com/video/av22807707 ...
- Tensorflow入门学习笔记汇总
一.环境准备 1.安装python:下载地址https://www.python.org/downloads/windows/下载并安装(推荐python3) 2.安装对应python版本的库:htt ...
- jvm字节码和类加载机制
Class类文件的结构 任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来说,类或接口并不一定都得定义在文件里(类和接口也可以用反射的方式通过类加载器直接生成) Class文件时一组以 ...
- Spring Boot Web应用开发 CORS 跨域请求支持
一.Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等 CORS与JSONP相比 1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求. 2. 使用C ...
- 正确卸载vs2015及以前版本方式
官网工具:https://github.com/Microsoft/VisualStudioUninstaller/releases 亲自测试过,很好用. (完)