博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RR隔离级别下通过next-key locks 避免幻影读
阅读量:5970 次
发布时间:2019-06-19

本文共 16247 字,大约阅读时间需要 54 分钟。

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

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)

幻影读(s)

什么是幻影读

同一事务保证了一致性读后,查询时对提交的事务是不可见的,但是变更的时候是可见的,所以就有可能引发幻影读

为什么会导致幻影读

对于update或delete操作(可以使用 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)

幻影读(s)

什么是幻影读

同一事务保证了一致性读后,查询时对提交的事务是不可见的,但是变更的时候是可见的,所以就有可能引发幻影读

为什么会导致幻影读

对于update或delete操作(可以使用 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

 

转载于:https://www.cnblogs.com/Bccd/p/7543903.html

你可能感兴趣的文章
我的友情链接
查看>>
浅谈如何用We7站群平台打造垂直性政务网站
查看>>
我的友情链接
查看>>
Go bytes包
查看>>
Spring MVC请求处理流程分析
查看>>
ORACLE--Connect By、Level、Start With的使用(Hierarchical query-层次查询)
查看>>
生产环境MySQL 5.5.x单机多实例配置实践
查看>>
Web应用工作原理、动态网页技术
查看>>
EXCEL工作表保护密码破解 宏撤销保护图文教程
查看>>
Catalan数(卡特兰数)
查看>>
Linux shell的条件判断、循环语句及实例
查看>>
JPA常用注解
查看>>
简单的设置
查看>>
常用命令1
查看>>
Windows Server 2012 DHCP故障转移
查看>>
Linux服务器配置和管理:虚拟机安装CentOS6.7
查看>>
掌握ajax
查看>>
ASA下邮件发送经常失败
查看>>
python3第八天(面向对象)
查看>>
我的友情链接
查看>>