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并发控制中 ...
随机推荐
- springclould feign客户端添加全局参数
用springclould feign作为调用服务的客户端,一般来说参数可以写在feignclient的方法参数里 有时需要所有feign请求都统一添加一些参数,例如token用于鉴权等,可以这样做: ...
- Git .gitignore 设置为全局global
在操作Git时,我们会将修改的内容$git add . 到Git,Git会提示我们哪些文件都修改了.此时提示中会包括系统自动修改的文件,bin文件等.而我们add到Git时,并不希望将这些文件也一同a ...
- window服务的使用
目前的项目中使用很多服务来进行实现.服务是依靠windows操作系统来实现.可以是定时器类型,比如定时执行费时的任务,这种任务时最多.也可以是一些服务(SOAP)的宿主,不在限制与iis,不现在限制于 ...
- sql创建作业--自动执行存储过程
创建自动执行存储过程: 1.创建参数 2.删除已有同名的作业 3. 创建作业 4.创建作业步骤 5.连接服务器 6.创建作业调度 7.启动作业 ALTER PROCEDURE dbo.sx_pro_A ...
- 覆盖alert对话框-自制Jquery.alert插件
Javascript 代码: (function ($) { 'use strict'; window.alert = $.alert = function (msg) { var defaultOp ...
- 关于ubuntu终端全屏的时候不能显示底部
最近在win7的电脑上装了ubuntu,也就是双系统.打算之后工作就直接进入ubuntu,减少之前win7和虚拟机之间的切换.进入ubuntu后,发现一个奇怪的问题是,在终端全屏的时候,底部总是有几行 ...
- Servlet The Filter
The Filter Filter不会产生Request或者是Response, 但是会在两者访问资源时, 对其作出改变.其可以作用于静态资源和动态资源. LifeCycle Filter会和Serv ...
- Web项目之Django实战问题剖析
基于AdminLTE-master模板的后台管理系统 左侧菜单栏的二级标签设计 面包屑 Django文件上传 后台管理系统CRM项目设计流程分析
- 解析IPV4报文 和IPV6 报文的 checksum
解析IPV4报文和IPV6报文的checksum的算法: 校验和(checksum)算法,简单的说就是16位累加的反码运算: 计算函数如下: 我们在计算时是主机字节序,计算的结果封装成IP包时是网络字 ...
- 基于Passthru的NDIS开发的个人理解
这几天对NDIS的学习,基本思路是:首先熟悉理论知识→然后下载一个例子进行研究→最后例子自己模仿扩展→最最后尝试自己写一个新的. Passthru是微软NDIS自己写的一个框架驱动,NDIS开发者可以 ...