文档章节

事务隔离级别-REPEATABLE-READ && 间隙锁

秋风醉了
 秋风醉了
发布于 2015/09/01 02:02
字数 1004
阅读 550
收藏 5

事务隔离级别-REPEATABLE-READ && 间隙锁

表结构

create table t(
 name varchar(255) primary key,
 id int not null,
 key idx_id (id)
);
insert into t(name,id) values ('a',15),
('b',10),('c',6),('d',10),('f',11),('zz',2);

Session A

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

Session B

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

Session A

mysql> select * from t;
+------+----+
| name | id |
+------+----+
| zz   |  2 |
| c    |  6 |
| b    | 10 |
| d    | 10 |
| f    | 11 |
| a    | 15 |
+------+----+
6 rows in set (0.00 sec)

mysql> select * from t where id = 10 for update;
+------+----+
| name | id |
+------+----+
| b    | 10 |
| d    | 10 |
+------+----+
2 rows in set (0.00 sec)

我们在Session A里执行当前读的select...for update操作,那这条sql语句时如何加锁的呢?看下图,

这幅图中有一个GAP锁,而且GAP锁看起来也不是加在记录上的,倒像是加载两条记录之间的位置,GAP锁有何用?

其实这个多出来的GAP锁,就是RR隔离级别,相对于RC隔离级别,不会出现幻读的关键。确实,GAP锁锁住的位置,也不是记录本身,而是两条记录之间的GAP。所谓幻读,就是同一个事务,连续做两次当前读 (例如:select * from t1 where id = 10 for update;),那么这两次当前读返回的是完全相同的记录 (记录数量一致,记录本身也一致),第二次的当前读,不会比第一次返回更多的记录 (幻象)。

如何保证两次当前读返回一致的记录,那就需要在第一次当前读与第二次当前读之间,其他的事务不会插入新的满足条件的记录并提交。为了实现这个功能,GAP锁应运而生。

如图中所示,有哪些位置可以插入新的满足条件的项 (id = 10),考虑到B+树索引的有序性,满足条件的项一定是连续存放的。记录[6,c]之前,不会插入id=10的记录;[6,c]与[10,b]间可以插入[10, aa];[10,b]与[10,d]间,可以插入新的[10,bb],[10,c]等;[10,d]与[11,f]间可以插入满足条件的[10,e],[10,z]等;而[11,f]之后也不会插入满足条件的记录。因此,为了保证[6,c]与[10,b]间,[10,b]与[10,d]间,[10,d]与[11,f]不会插入新的满足条件的记录,MySQL选择了用GAP锁,将这三个GAP给锁起来。

Insert操作,如insert [10,aa],首先会定位到[6,c]与[10,b]间,然后在插入前,会检查这个GAP是否已经被锁上,如果被锁上,则Insert不能插入记录。因此,通过第一遍的当前读,不仅将满足条件的记录锁上 (X锁),同时还是增加3把GAP锁,将可能插入满足条件记录的3个GAP给锁上,保证后续的Insert不能插入新的id=10的记录,也就杜绝了同一事务的第二次当前读,出现幻象的情况。

然后我们在Session B中做相应的Insert操作,验证一下上面的说法。

Session B

执行以下插入操作

mysql> select * from t;
+------+----+
| name | id |
+------+----+
| zz   |  2 |
| c    |  6 |
| b    | 10 |
| d    | 10 |
| f    | 11 |
| a    | 15 |
+------+----+
6 rows in set (0.00 sec)

mysql> insert t(name,id) values ('aa',10);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert t(name,id) values ('bb',10);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert t(name,id) values ('e',11);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>

可以看到我们执行了多次插入,都失败了,就是因为GAP上加了间隙锁的原因,导致插入不成功,也就防止了Session A第二次当前读的时候不会出现幻读。

当执行这条sql时insert t(name,id) values ('bb',10)时,相应的锁的信息;

mysql> use information_schema
Database changed
mysql> select * from INNODB_LOCKS;
+--------------+-------------+-----------+-----------+------------+------------+------------+-----------+----------+-----------+
| lock_id      | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+--------------+-------------+-----------+-----------+------------+------------+------------+-----------+----------+-----------+
| 11662:65:4:5 | 11662       | X,GAP     | RECORD    | `test`.`t` | idx_id     |         65 |         4 |        5 | 10, 'd'   |
| 11661:65:4:5 | 11661       | X         | RECORD    | `test`.`t` | idx_id     |         65 |         4 |        5 | 10, 'd'   |
+--------------+-------------+-----------+-----------+------------+------------+------------+-----------+----------+-----------+
2 rows in set (0.00 sec)

===========END===========

本文转载自:http://hedengcheng.com/?p=771

秋风醉了
粉丝 253
博文 532
码字总数 405557
作品 0
朝阳
程序员
私信 提问
加载中

评论(0)

MySQL MVCC && 事务隔离级别 && 锁

MySQL MVCC && 事务隔离级别 && 锁 InnoDB多版本并发控制——MVCC http://my.oschina.net/xinxingegeya/blog/208821 MySQLS锁X锁read lockwrite lock http://my.oschina.net/xinxingegeya/bl......

秋风醉了
2014/07/30
646
0
简单整理一下mysql的隔离级别;

READ UNCOMMITTED SELECT语句以非锁定方式被执行,但是一个可能更早期版本的记录会被用到。因此,使用这个隔离级别,比如,读是不连贯的。这也被称为“脏读”( dirty read)。另外,这个隔离...

世界和平维护者
2016/10/06
37
0
【面试高频!】数据库事务/事务的作用/数据库事务ACID属性 / 特性/事务的隔离性/数据库事务隔离级别/ 数据库的隔离级别导致问题/数据库事务的使用/mysql的事务死锁/ 快速解决mysql死锁问

数据库事务: 针对数据库的某一组操作要么全部成功,要么全部失败。 事务的作用 数据库事务ACID属性 / 特性 原子性(Atomicity):要么全部完成,要么全部不完成。 一致性(Consistency):事务必...

菜丸
前天
0
0
Mysql事务隔离性与相关锁的总结

事务隔离级别 隔离级别 脏读 不可重复读 幻读 读未提交 可以出现 可以出现 可以出现 读提交 不允许出现 可以出现 可以出现 可重复读 不允许出现 不允许出现 可以出现 序列化 不允许出现 不允...

hongdada
01/23
0
0
事务的四大特性和隔离级别

一.什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。 二.事务的 四个特性(ACID ) 事务具有四个特性:原子性( Atomic...

LYQ1990
2016/04/29
126
1

没有更多内容

加载失败,请刷新页面

加载更多

唐宇迪-人工智能学习路线(下篇)

唐宇迪:51CTO微职位讲师,计算机博士,人工智能专家 内容梗概:介绍人工智能学习步骤和知识框架。人工智能的学习可以拆分为7步,此为4-7步:下篇。 第4步:深度学习 1)深度学习概述 终于说...

osc_jcfo5qp3
25分钟前
13
0
Vue权限管理解决方案

中文 | English vue-access-control []() :gem: Vue权限管理解决方案 介绍 Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个...

osc_m8miia9c
26分钟前
12
0
工欲善其事,必先利其器——DevOps中如何管理工具包

一、背景 作为DevOps交付流水线的开发者,为支持CI/CD中各项任务的自动化,都需要依赖多种包管理工具来下载各种相关的工具,比如针对产生最终交付件的构建过程,就需要在构建流程的第一步,自...

osc_63i522q0
28分钟前
17
0
G++编译期间的四个过程

编写文件mian.cpp,代码示例是 https://www.cnblogs.com/zjiaxing/p/5557549.html 中的。 1 #include <iostream> 2 using namespace std; 3 #define pi 3.14 4 static int t = 1;......

osc_4qu6doqx
28分钟前
13
0
MySQL5.7详解安装配置

MySQL5.7详解安装配置 步骤1:下载安装 可以去mysql的官网下载,也可以直接下载小落上传到CSDN的资源 官网下载地址:https://dev.mysql.com/downloads/installer/ 本博客使用64位免安装版进行...

osc_8exjk9uk
31分钟前
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部