RR模式下NEXT-KEY LOCK范围到底有多大

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 我们知道MYSQL NEXT-KEY LOCK是用来防止幻读,在RR模式下就有了用武之地 实际就是当前行锁+前后的一个区间,但是这个区间到底有多大? 是简单的一个辅助索引列上的闭区间吗? 测试全部是在RR模式下RC模式不存在 建立测试表: CREATE TA...
我们知道MYSQL NEXT-KEY LOCK是用来防止幻读,在RR模式下就有了用武之地
实际就是当前行锁+前后的一个区间,但是这个区间到底有多大?
是简单的一个辅助索引列上的闭区间吗?
测试全部是在RR模式下RC模式不存在

建立测试表:
CREATE TABLE `test` (
  `a` int(11) NOT NULL DEFAULT '0',
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`),
  KEY `b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


插入几行数据


mysql> insert into test values(10,2);
Query OK, 1 row affected (0.01 sec)


mysql> insert into test values(15,2);
Query OK, 1 row affected (0.02 sec)


mysql> insert into test values(20,4);
Query OK, 1 row affected (0.01 sec)


mysql> insert into test values(25,6);
Query OK, 1 row affected (0.02 sec)


mysql> insert into test values(99,8);
Query OK, 1 row affected (0.00 sec)


mysql> commit;
Query OK, 0 rows affected (0.00 sec)


mysql> select * from test;
+----+------+
| a  | b    |
+----+------+
| 10 |    2 |
| 15 |    2 |
| 20 |    4 |
| 25 |    6 |
| 99 |    8 |
+----+------+
5 rows in set (0.00 sec)


会话A:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test where b=4 for update;
+----+------+
| a  | b    |
+----+------+
| 20 |    4 |
+----+------+
1 row in set (0.00 sec)

会话B:
mysql> select * from test where b=2 for update;
+----+------+
| a  | b    |
+----+------+
| 10 |    2 |
| 15 |    2 |
+----+------+
2 rows in set (0.00 sec)

mysql> select * from test where b=6 for update;
+----+------+
| a  | b    |
+----+------+
| 25 |    6 |
+----+------+
1 row in set (0.00 sec)


都没有问题,那显然这些列都没加X锁,那是不是可以简单的理解锁定是
一个2-6的区间不包含2和6呢?
看下面的语句:
mysql> insert into test values(16,2);
^CCtrl-C -- sending "KILL QUERY 3" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into test values(16,6);
^CCtrl-C -- sending "KILL QUERY 3" to server ...
Ctrl-C -- query aborted.
ERROR 1317 (70100): Query execution was interrupted
均锁定了

但是
mysql> insert into test values(14,2);
Query OK, 1 row affected (0.21 sec)
mysql> insert into test values(26,6);
Query OK, 1 row affected (0.02 sec)
是可以执行的。

这也证明了我们刚才的结论是不正确的,我们分析一下

| 15 |    2 |
| 20 |    4 |
| 25 |    6 |
这是原始的记录我们对4进行了for update,为了更小的缩小范围
实际上INNODB把锁的方位定义到了
b列2 a列(15到正无穷) b列4 全部 b列6 a列(负无穷到25) 
之间全部的范围,这看起来好像不是一个连续的区间,但是如果理解B+树索引
同时INNODB在处理相同的值的时候按照主键升序进行排列就出现了一个连续的
区间,我们来画一下,假设叶子节点如下排列,



实际上这样我们就能看出这样一个范围,如果我们插入的是

 values(16,2)显然在这个范围内它应该插入在2 15 4 20 之间,所以锁定

 values(16,6)显然也在范围,他应该插入到4 206 25 之间,所以锁定

 values(14,2)显然不在这个范围,他应该在2 10 2 15之间插入,所以OK

 values(26,6)6 258 99 之间当然也可以。

如果要插入(3,3)显然不行,因为首先是按照key排序的他肯定在这个范围内。


最后我们得出我们的结论:

b2 a(15到正无穷)

b4 全部

b6 a(负无穷到25)

这样一个范围的插入全部不允许,当然2 15  6 25本身不包含因为可以for update.

其实这样做也是为了最小化锁定范围提高并发,所以辅助索引上的gap lock不仅取决

于辅助索引列还取决于主键列的值,但是要注意这个锁是在辅助索引上的,而不是
主键上。
还有一点需要提醒:
如果锁定是边界记录如上图的
b=2 for update

b=8 for update
那么锁定的范围将变大
b=2 for update锁定的是 b列负无穷 到 b列4 a列(负无穷到20) 
如图:
这里将虚拟行infimum写出来代表负无穷

b=8 for update锁定的是b列 6 a列(25 到正无穷) 到 b列 正无穷
如图:
这里将supremum虚拟行列出来代表正无穷


实际就是看图就理解了

最后就是需要验证:

验证从2个方面

1、对辅助索引的页中链表进行分析,如果在辅助索引页内的链表按照首先是KEY排序然后KEY相同的按照PRIMARY KEY排序那么基本就验证了我们的说法
   这个随后可以补上

2、源码查看,源码过于庞大就是B+树索引数据结构的建立,查找,插入,删除都非常难看懂,如果要到我们需要的证据非常困难,以后尽力。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
225 2
|
7月前
|
存储 SQL 算法
Innodb锁机制:Next-Key Lock 浅谈
Innodb锁机制:Next-Key Lock 浅谈
234 0
lock和synchtonized的区别
lock和synchtonized的区别
|
SQL 缓存 关系型数据库
《深入理解共享锁lock in share mode排他锁for update区别》
《深入理解共享锁lock in share mode排他锁for update区别》
《深入理解共享锁lock in share mode排他锁for update区别》
|
关系型数据库 MySQL 索引
MySQL next-key lock 加锁范围总结
三篇文章分别通过实际操作,介绍了主键、非主键唯一索引、普通索引、普通字段四个方面介绍了加锁的范围。 本篇文章再做一个总结。
706 0
|
缓存 NoSQL Java
缓存系列文章--8.热点key问题(mutex key)
   转载请注明出处哈:http://carlosfu.iteye.com/blog/2269678  一、引出热点key问题          我们通常使用 缓存 + 过期时间的策略来帮助我们加速接口的访问速度,减少了后端负载,同时保证功能的更新,一般情况下这种模式已经基本满足要求了。
1274 0
|
NoSQL 关系型数据库 MySQL
如何查找到底是谁执行了FTWL导致Waiting for global read lock
在MySQL · 特性分析 · 到底是谁执行了FTWL中 文章中,分析了为何出现大量Waiting for global read lock的连接。但是实际操作起来很多gdb版本不支持pset操作,而且连接过多,导致不可能手动打印每一个THD的state,所以笔者写了一个gdb的脚本供大家使用: 首先,先保存下面脚本到/tmp/getlockconn MySQL8.
2692 0
|
网络协议 数据安全/隐私保护 网络架构