RR隔离级别下通过next-key locks 避免幻影读
---恢复内容开始---
mysql innodb目前使用范围最广的两种隔离级别为RC和RR,RR修复了RC中所存在的不可重复读
READ COMMITED
不可重复读
在同一事务中两次查看的结果集不同,如下session1的查看结果集受session2提交的事物影响
05:47:35[test](;)> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+ session1
03:28:11[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 03:28:21[test](;)> select * from t1;
Empty set (0.01 sec)
session2
03:28:27[test](;)> insert into t1 values(1,1,1,1,1);
Query OK, 1 row affected (0.00 sec)
03:29:25[test](;)> select * from t1;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 1 | 1 | 1 | 1 | 1 |
+----+------+------+------+------+
1 row in set (0.00 sec)
幻影读(Phantom Rows)
什么是幻影读
同一事务保证了一致性读后,查询时对提交的事务是不可见的,但是变更的时候是可见的,所以就有可能引发幻影读
为什么会导致幻影读
对于update或delete操作(可以使用SELECT
with FOR UPDATE
or LOCK IN SHARE MODE
来进行模拟),innodb只加记录锁(满足条件索引记录)而不是gap锁,gap锁只用于外键约束和duplicate key的检查,所以允许另一事务在锁定的记录旁边自由插入新记录
如col2上有索引,在满足col2>5的条件索引上加索引(对于RC,只在col2为10的索引记录上加X lock),所以在另一会话总插入col2 为非10的记录则会成功
set tx_isolation='read-committed' ;
session 1
07:46:16[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 07:46:20[test](;)> select * from t1 where col2>5 for update;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 2 | 2 | 10 | 2 | 2 |
+----+------+------+------+------+
1 row in set (0.00 sec)
07:44:48[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 07:46:36[test](;)> insert into t1 values(3,3,6,3,3);
Query OK, 1 row affected (0.00 sec) 07:46:38[test](;)> commit;
Query OK, 0 rows affected (0.10 sec)
07:46:31[test](;)> select * from t1 where col2>5;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 3 | 3 | 6 | 3 | 3 |
| 2 | 2 | 10 | 2 | 2 |
+----+------+------+------+------+
2 rows in set (0.00 sec)
若col2上无索引,也会是同样的结果现象,如果条件字段上无索引,innodb会先将所有行都加上锁,然后返回给server层根据条件筛选,满足条件则释放行锁,不满足条件则不释放
REPEATABLE READ
如何实现可重复读
事物开始时记录当前的快照版本,事务期间读取的都是事务开始时的快照版本
如何避免幻影读
通过 next-key lock 锁机制,是由index-row lock和gap lock组合成的
如,条件为col2>5,会在区间上[1,5],(5,正无穷)加index-row lock
08:30:02[test](;)> set tx_isolation='repeatable-read' ;
08:30:49[test](;)> select * from t1;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 10 | 2 | 10 |
+----+------+------+------+------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
08:31:02[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 08:31:05[test](;)> select * from t1 where col2>5 for update;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 2 | 2 | 10 | 2 | 10 |
+----+------+------+------+------+
1 row in set (0.00 sec)
08:30:51[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 08:32:11[test](;)> insert into t1 values(3,3,6,3,6);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
---恢复内容结束---
mysql innodb目前使用范围最广的两种隔离级别为RC和RR,RR修复了RC中所存在的不可重复读
READ COMMITED
不可重复读
在同一事务中两次查看的结果集不同,如下session1的查看结果集受session2提交的事物影响
05:47:35[test](;)> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+ session1
03:28:11[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 03:28:21[test](;)> select * from t1;
Empty set (0.01 sec)
session2
03:28:27[test](;)> insert into t1 values(1,1,1,1,1);
Query OK, 1 row affected (0.00 sec)
03:29:25[test](;)> select * from t1;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 1 | 1 | 1 | 1 | 1 |
+----+------+------+------+------+
1 row in set (0.00 sec)
幻影读(Phantom Rows)
什么是幻影读
同一事务保证了一致性读后,查询时对提交的事务是不可见的,但是变更的时候是可见的,所以就有可能引发幻影读
为什么会导致幻影读
对于update或delete操作(可以使用SELECT
with FOR UPDATE
or LOCK IN SHARE MODE
来进行模拟),innodb只加记录锁(满足条件索引记录)而不是gap锁,gap锁只用于外键约束和duplicate key的检查,所以允许另一事务在锁定的记录旁边自由插入新记录
如col2上有索引,在满足col2>5的条件索引上加索引(对于RC,只在col2为10的索引记录上加X lock),所以在另一会话总插入col2 为非10的记录则会成功
set tx_isolation='read-committed' ;
session 1
07:46:16[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 07:46:20[test](;)> select * from t1 where col2>5 for update;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 2 | 2 | 10 | 2 | 2 |
+----+------+------+------+------+
1 row in set (0.00 sec)
07:44:48[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 07:46:36[test](;)> insert into t1 values(3,3,6,3,3);
Query OK, 1 row affected (0.00 sec) 07:46:38[test](;)> commit;
Query OK, 0 rows affected (0.10 sec)
07:46:31[test](;)> select * from t1 where col2>5;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 3 | 3 | 6 | 3 | 3 |
| 2 | 2 | 10 | 2 | 2 |
+----+------+------+------+------+
2 rows in set (0.00 sec)
若col2上无索引,也会是同样的结果现象,如果条件字段上无索引,innodb会先将所有行都加上锁,然后返回给server层根据条件筛选,满足条件则释放行锁,不满足条件则不释放
REPEATABLE READ
如何实现可重复读
事物开始时记录当前的快照版本,事务期间读取的都是事务开始时的快照版本
如何避免幻影读
通过 next-key lock 锁机制,是由index-row lock和gap lock组合成的
如,条件为col2>5,会在区间上[1,5],(5,正无穷)加index-row lock
08:30:02[test](;)> set tx_isolation='repeatable-read' ;
08:30:49[test](;)> select * from t1;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 10 | 2 | 10 |
+----+------+------+------+------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
08:31:02[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 08:31:05[test](;)> select * from t1 where col2>5 for update;
+----+------+------+------+------+
| id | col1 | col2 | col3 | col4 |
+----+------+------+------+------+
| 2 | 2 | 10 | 2 | 10 |
+----+------+------+------+------+
1 row in set (0.00 sec)
08:30:51[test](;)> begin;
Query OK, 0 rows affected (0.00 sec) 08:32:11[test](;)> insert into t1 values(3,3,6,3,6);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
RR隔离级别下通过next-key locks 避免幻影读的更多相关文章
- InnoDB MVCC RR隔离级别下的数据可见性总结
一.背景 熟悉数据库隔离级别的人都知道,在RR(可重复读)隔离级别下,无论何时多次执行相同的SELECT快照读语句,得到的结果集都是完全一样的,即便两次SELECT语句执行期间,其他事务已经改变了该查 ...
- [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?
Server version: 5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...
- MySQL Transaction--RR事务隔离级别下加锁测试
============================================================================== 按照非索引列更新 在可重复读的事务隔离级别 ...
- Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...
- MySQL Transaction--RC事务隔离级别下加锁测试
==============================================================================非索引列更新 在读提交的事务隔离级别下,在非 ...
- Innodb 中 RR 隔离级别能否防止幻读?
问题引出 我之前的一篇博客 数据库并发不一致分析 有提到过事务隔离级别以及相应加锁方式.能够解决的并发问题. 标准情况下,在 RR(Repeatable Read) 隔离级别下能解决不可重复读(当行修 ...
- InnoDB在MySQL默认隔离级别下解决幻读
1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...
- 浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题
本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- MySQL--REPEATABLE-READ隔离级别下读取到的“重复数据”
在MySQL中,使用MVCC来实现REPEATABLE-READ隔离级别,由于SELECT操作不会对数据加锁,其他回话可以修改当前回话所读取过的数据而不会被阻塞,因此读写不冲突. 在MVCC并发控制中 ...
随机推荐
- arcgis jsapi接口入门系列(6):样式
symbol: function () { //线样式 //样式详情请看官方文档 let style = { //线颜色,支持多种格式: //CSS color string:例如"dodg ...
- 将Android系统源码导入Android studio的方法
Android源码目录结构如下: |-- Makefile|-- abi (applicationbinary interface,应用程序二进制接口,生成libgabi++.so相关库文件)|-- ...
- 【读书笔记】构建之法(CH7~CH8)
MSF九大原则: 1. 推动信息共享与沟通:“谐”,Alert 2. 为共同的远景而工作:目标明确—用户/老板 3. 充分授权和信任: 4. 各司其职,对项目共同负责: 5. 交付增量的价值: 6. ...
- Azure School女神相邀,把每分钟都过的更充实
也许你不姓「牛」,但是你技术牛啊 所以,请容我叫你一声「牛郎」 (讲真,只是因为你技术牛,不是其他啥原因哈) 平时忙到昏天黑地,一心一意为技术的你 注意看一下日历,因为: !!!七夕节(8月28日)到 ...
- MySQL优化汇总
1)mysql优化汇总,转载自网络
- js 双向绑定
//双向绑定实例 <input name="" ng-bind-123="name" /> function DataBinder( object_ ...
- UVA 11374 Airport Express (最短路)
题目只有一条路径会发生改变. 常见的思路,预处理出S和T的两个单源最短路,然后枚举商业线,商业线两端一定是选择到s和t的最短路. 路径输出可以在求最短路的同时保存pa数组得到一棵最短路树,也可以用di ...
- input提示文字;placeholder字体修改
在很多网站上我们都看到input输入框显示提示文字,让我们一起来看看如果在input输入框中显示提示文字.我们只需要在<input>标签里添加:placeholder="提示文字 ...
- Java代码实现文件上传(转载)
刚刚发表了一篇Java发送电子邮件,以前真是没注意,commons里这么多常用项目,惭愧呀,直到现在回顾;要学习的真是太多了,还是缺少真正的学习能力... 这里用到的是commons-fileuplo ...
- Luogu P1782 旅行商的背包
题目传送门 卡常背包果然名不虚传 算法主体就是两种背包分开跑,先跑多重背包,再跑奇货 不知道为什么,这题二进制拆分好像要比单调队列优化快一些 然后这题毒瘤的地方就出来了: 如果一件物品的体积\(\ti ...