---恢复内容开始---

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 避免幻影读的更多相关文章

  1. InnoDB MVCC RR隔离级别下的数据可见性总结

    一.背景 熟悉数据库隔离级别的人都知道,在RR(可重复读)隔离级别下,无论何时多次执行相同的SELECT快照读语句,得到的结果集都是完全一样的,即便两次SELECT语句执行期间,其他事务已经改变了该查 ...

  2. [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?

    Server version:         5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...

  3. MySQL Transaction--RR事务隔离级别下加锁测试

    ============================================================================== 按照非索引列更新 在可重复读的事务隔离级别 ...

  4. Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)

    Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...

  5. MySQL Transaction--RC事务隔离级别下加锁测试

    ==============================================================================非索引列更新 在读提交的事务隔离级别下,在非 ...

  6. Innodb 中 RR 隔离级别能否防止幻读?

    问题引出 我之前的一篇博客 数据库并发不一致分析 有提到过事务隔离级别以及相应加锁方式.能够解决的并发问题. 标准情况下,在 RR(Repeatable Read) 隔离级别下能解决不可重复读(当行修 ...

  7. InnoDB在MySQL默认隔离级别下解决幻读

    1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...

  8. 浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题

    本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

  9. MySQL--REPEATABLE-READ隔离级别下读取到的“重复数据”

    在MySQL中,使用MVCC来实现REPEATABLE-READ隔离级别,由于SELECT操作不会对数据加锁,其他回话可以修改当前回话所读取过的数据而不会被阻塞,因此读写不冲突. 在MVCC并发控制中 ...

随机推荐

  1. AJAX的JSON方式传回方法

    AJAX返回数据的类型有两种,一种是TEXT类型,一种是JSON类型. 使用TEXT类型,访问数据库后将结果拼接成字符串,返回时在拆分成数组使用. JSON直接将结果转成JSON数据,返回时直接使用. ...

  2. idea npm 调试报错解决办法

    1.用egg框架的开发时候,egg 提供本地开发和调试.点击idea 的debug 按钮时候报如下错误: Please specify npm or yarn package: cannot find ...

  3. SQL 时间日期函数

    1.获取当前日期GetDate getdate()函数以datetime数据类型的格式返回当前SQLServer服务器所在计算机的日期和时间.其语法格式为getdate().返回值舍入到最近的秒小数部 ...

  4. POJ 2831 Can We Build This One?

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 1728   Accepted: 643 Case Time Limit: 2 ...

  5. python之数据类型补充

    1. capitalize (首字母大写) 例题: s = "alex wusir" s1 = s.capitalize() # 格式 print(s1) ''' 输出结果 Ale ...

  6. Spring启动流程—源码解读

    https://blog.csdn.net/yangliuhbhd/article/details/80790761 Spring的AbstractApplicationContext的refresh ...

  7. iCheck获取单选和复选框的值和文本

    //获取单选和复选框的值//parameters.type:"radio","checkbox"//parameters.name:input-name//pa ...

  8. python-DB模块

    基于python的接口测试框架设计   连接数据库 首先是连接数据库的操作,最好是单独写在一个模块里, 然后便于方便的调用,基于把connection连接放在__init__()方法里 然后分别定义D ...

  9. swift中使用sqlite3

    import Foundation /** 1. 打开数据库 2. 如果没有数据表,需要首先创表 3. 数据操作 */ class SQLite { var db: COpaquePointer = ...

  10. sass --watch 失败bug

    NameError: uninitialized constant Sass::Plugin::Compiler::SassListen 网上说法是sass v3.2.10有bug 但是我版本3.5. ...