1.结论

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

2.幻读是什么

事务A,先执行:

update table set name=“hh” where id>3;

结果为:

OK row xx 表名成功影响多少行数据

事务B,后执行,并且提交:

insert into table values(11, uu);

commit;

事务A,然后再select一下:

select * from table where id>3

结果集为:

11,uu

事务A懵了,我特么不是id>3全部更新了吗

这次是已提交事务B对事务A产生的影响,这个影响叫做“幻读”。

幻读和不可重复读的区别是,前者是一个范围,后者是本身

3. 怎么解决的?

3.1. 当前读

所谓当前读,指的是加锁的select(S或者X), update, delete等语句。在RR的事务隔离级别下,数据库会使用next-key locks来锁住本条记录以及索引区间。

拿上面那个例子来说,在RR的情况下,假设使用的是当前读,加锁了的读

select * from table where id>3 锁住的就是id=3这条记录以及id>3这个区间范围,锁住索引记录之间的范围,避免范围间插入记录,以避免产生幻影行记录。

3.2. 普通读

因为普通读是不会加锁的读,故不会有next-key locks的使用,解决幻读的手段是MVVC

mvvc会给每行元组加一些辅助字段,记录创建版本号和删除版本号。

而每一个事务在启动的时候,都有一个唯一的递增的版本号。每开启一个新事务,事务的版本号就会递增。

默认的隔离级别(REPEATABLE READ)下,增删查改变成了这样:

SELECT
读取创建版本小于或等于当前事务版本号,并且删除版本为空或大于当前事务版本号的记录。这样可以保证在读取之前记录是存在的
INSERT
将当前事务的版本号保存至行的创建版本号
UPDATE
新插入一行,并以当前事务的版本号作为新行的创建版本号,同时将原记录行的删除版本号设置为当前事务版本号
DELETE
将当前事务的版本号保存至行的删除版本号

  比如我插入一条记录, 事务id 假设是1 ,那么记录如下:也就是说,创建版本号就是事务版本号。

id

name

createversion

deleteversion

1 wxt 1  

  如果我更新的话,事务id假设是2

id

name

createverison

deleteversion

1 wxt 1 2
1 taotao 2  

  这里是把name更新为taotao,原来的元组deleteversion版本号为这个事务的id,并且新增一条

  如果我删除的话,假设事务是id=3

id

name

createverison

deleteversion

1 taotao 2 3

  重点来了

  现在我读取的话,必须同时满足两个条件的

  1. 读取创建版本小于或等于当前事务版本号   这意味着数据在这个事务之前被创建
  2. 删除版本为空或大于当前事务版本号的记录。  这意味着删除操作在这个事务之后发生

假设事务A的id=10

现在update table set name=“hh” where id>3;执行这条语句

事务B的id=11

insert into table values(11, uu);

最后事务A(id=10)在此读取

select * from table where id>3

根据上述的规则,

读取创建版本好小于等于当前事务的→那么(4,a)(5,b)(4,hh)(5,hh)

上面规则的输出作为下面规则的输入的话

删除版本为空或大于当前事务版本号的记录→(4,hh)(5,hh)

如此读取就没有读取到事务B新插入的那行,解决幻读。

如果事务B是更新id=4 的元组name=cc呢

同理,根据update的规则

然后根据select的规则去读取的话,得到的还是(4,hh)(5,hh)

参考:InnoDB怎么解决幻读的?

InnoDB在MySQL默认隔离级别下解决幻读的更多相关文章

  1. MYSQL事件隔离级别以及复读,幻读,脏读的理解

    一.mysql事件隔离级别 1未提交读(READUNCOMMITTED) 另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)( 隔离级别最低,并发性能高 ) 2 ...

  2. sqlserver默认隔离级别下并发批量update同一张表引起的死锁

    提到死锁,最最常规的场景之一是Session1 以排它锁的方式锁定A表,请求B表,session2以排它锁的方式锁定B表,请求A表之类的,访问顺序不一致导致死锁的情况本文通过简化,测试这样一种稍显特殊 ...

  3. MySQL默认隔离级别为什么是RR

    曾多次听到“MySQL为什么选择RR为默认隔离级别”的问题,其实这是个历史遗留问题,当前以及解决,但是MySQL的各个版本沿用了原有习惯.历史版本中的问题是什么,本次就通过简单的测试来说明一下. 1. ...

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

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

  5. MySQL的可重复读级别能解决幻读吗

    引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...

  6. MySQL的可重复读级别能解决幻读问题吗?

    之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于幻读, ...

  7. 面试官:MySQL的可重复读级别能解决幻读问题吗?

    引言 之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于 ...

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

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

  9. InnoDB解决幻读的方案——LBCC&MVCC

    最近要在公司内做一次技术分享,思来想去不知道该分享些什么,最后在朋友的提示下,准备分享一下MySQL的InnoDB引擎下的事务幻读问题与解决方案--LBCC&MVCC.经过好几天的熬夜通宵,终 ...

随机推荐

  1. Elasticsearch实战 | 必要的时候,还得空间换时间!

    1.应用场景 实时数据流通过kafka后,根据业务需求,一部分直接借助kafka-connector入Elasticsearch不同的索引中. 另外一部分,则需要先做聚类.分类处理,将聚合出的分类结果 ...

  2. centos7之Python3.74安装

    安装版本:Python3.74 系统版本:centos7 系统默认安装Python2.7,保留. 安装/usr/bin/Python3 安装需要root权限. 安装Python3的准备工作: 1.安装 ...

  3. 7.19 包 logging模块 hashlib模块 openpyxl模块 深浅拷贝

    包 包是什么 他是一系列文件的结合体,表现形式就是文件夹 包的本质还是模块 他通常会有__init__.py文件 我们首先回顾一下模块导入的过程 import module首次导入模块(.py文件) ...

  4. 基于Visual C#的AutoCAD开发——一些网址

    https://blog.csdn.net/xwebsite/article/details/5578446 http://www.cadgj.com/?p=1504

  5. vs 中本地 git 的基本使用

    用 svn  有个毛病就是只有在改好了之后,才能提交.当周期比较长的时候,连自己都不知道自己改了什么东西,或者意外断电的时候,vs 中已保持的项目都有可能被 vs 去掉. 这个时候,使用 git 创建 ...

  6. zuul集成Sentinel最新的网关流控组件

    一.说明 Sentinel 网关流控支持针对不同的路由和自定义的 API 分组进行流控,支持针对请求属性(如 URL 参数,Client IP,Header 等)进行流控.Sentinel 1.6.3 ...

  7. 【已解决】Https请求—未能创建 SSL/TLS 安全通道

    在做项目的微信推送消息功能时,由于微信并发量大,导致其它第三方接口调用时直接挂掉报错. 问题: 测试工程师做压测,100个线程同时调用微信和XX站的接口,日志报XX站的“请求被中止: 未能创建 SSL ...

  8. JMM内存模型详解(一)

    本文开始死磕JMM(Java内存模型)由于知识点较多,分来写 该文为JMM第一篇 技术往往是枯燥的,本文文字较多 1. JMM是什么? 其实JMM很好理解,我简单的解释一下,在Java多线程中我们经常 ...

  9. 消息中间件——RabbitMQ(六)理解Exchange交换机核心概念!

    前言 来了解RabbitMQ一个重要的概念:Exchange交换机 1. Exchange概念 Exchange:接收消息,并根据路由键转发消息所绑定的队列. 蓝色框:客户端发送消息至交换机,通过路由 ...

  10. Springboot源码分析之AbstractAdvisorAutoProxyCreator

    摘要: Spring的代理在上层中主要分为ProxyCreatorSupport和ProxyProcessorSupport,前者是基于代理工厂,后者是基于后置处理器,也可以认为后置就是自动代理器.当 ...