InnoDB在MySQL默认隔离级别下解决幻读
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 |
重点来了
现在我读取的话,必须同时满足两个条件的
- 读取创建版本小于或等于当前事务版本号 这意味着数据在这个事务之前被创建
- 删除版本为空或大于当前事务版本号的记录。 这意味着删除操作在这个事务之后发生
假设事务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在MySQL默认隔离级别下解决幻读的更多相关文章
- MYSQL事件隔离级别以及复读,幻读,脏读的理解
一.mysql事件隔离级别 1未提交读(READUNCOMMITTED) 另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)( 隔离级别最低,并发性能高 ) 2 ...
- sqlserver默认隔离级别下并发批量update同一张表引起的死锁
提到死锁,最最常规的场景之一是Session1 以排它锁的方式锁定A表,请求B表,session2以排它锁的方式锁定B表,请求A表之类的,访问顺序不一致导致死锁的情况本文通过简化,测试这样一种稍显特殊 ...
- MySQL默认隔离级别为什么是RR
曾多次听到“MySQL为什么选择RR为默认隔离级别”的问题,其实这是个历史遗留问题,当前以及解决,但是MySQL的各个版本沿用了原有习惯.历史版本中的问题是什么,本次就通过简单的测试来说明一下. 1. ...
- [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?
Server version: 5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...
- MySQL的可重复读级别能解决幻读吗
引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...
- MySQL的可重复读级别能解决幻读问题吗?
之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于幻读, ...
- 面试官:MySQL的可重复读级别能解决幻读问题吗?
引言 之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于 ...
- Innodb 中 RR 隔离级别能否防止幻读?
问题引出 我之前的一篇博客 数据库并发不一致分析 有提到过事务隔离级别以及相应加锁方式.能够解决的并发问题. 标准情况下,在 RR(Repeatable Read) 隔离级别下能解决不可重复读(当行修 ...
- InnoDB解决幻读的方案——LBCC&MVCC
最近要在公司内做一次技术分享,思来想去不知道该分享些什么,最后在朋友的提示下,准备分享一下MySQL的InnoDB引擎下的事务幻读问题与解决方案--LBCC&MVCC.经过好几天的熬夜通宵,终 ...
随机推荐
- H5 Handlebars的简单使用
扫码关注公众号,不定期更新干活 web 开发中,js 解析JSON 是经常的事情.非常繁琐.handlebars 使用了模版,只要你定义一个模版,提供一个json对象,handlebars 就能吧js ...
- 笑谈CSS的伪元素
今晚上我们来简单的聊一聊CSS的伪元素,多说无益,开聊 GG: 话说盘古开天辟地之时. QQ:嗨,咱今天还能讲的完吗?您给来点实际的啊. GG:要听实际的是吧,得嘞,那今天咱就来聊一聊CSS里的伪元素 ...
- 如何永久破解IDEA 2019.2
声明: 支持知识产权,支持正版产权,以下仅限个人学习使用IDEA工具时随笔记录,禁止商业使用. 以下个人提供的激活补丁和激活码来源,均由网上下载,各位也可以自行查找. IDEA官网下载地址:https ...
- Unity经典案例之:Fire Balls 多个圆环以及圆环的变速变向
版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...
- SpringMVC 源码解析
前言 年初面试时接触到一道面试题,在聊到SpringMVC时提到了SpringMVC的开发者为何要设计父子容器呢,又或者说是父子容器的设计有什么更实际的作用呢? 首先 ...
- 集成 Spring Boot 常用组件的后台快速开发框架 spring-boot-plus 国
spring-boot-plus是一套集成spring boot常用开发组件的后台快速开发框架 Purpose 每个人都可以独立.快速.高效地开发项目! Everyone can develop pr ...
- elk安装与搭建
Elasticsearch安装配置 ·下载elasticsearch.tar.gz包,解压压缩包.(此处为单机版es,集群请参考 https://www.cnblogs.com/lazycxy/p/9 ...
- unity_UGUI养成之路01
1.UGUI_UI之音量设计 2.控制音量音效的开关 实现开和关的互斥点击 实现开与关画面的显示 注意,上图并未选择分组.具体原因博主尚不清楚如果有知道的可以告知一二,谢谢各位!!! 代码: usi ...
- jq ajax传递json对象到服务端及contentType的用法
目录 0.一般情况下,通过键值对的方式将参数传递到服务端 1.ajax 传递复杂json对象到服务端 2.content-Type 对asp.net mvc项目的重要性 0.一般情况下,通过键值对的方 ...
- runnable和thread实现多线程的区别
下面以典型的买票程序(基本都是以这个为例子)为例,来说明二者的区别. 首先通过继承Thread类实现,代码如下: class MyThread extends Thread{ private int ...