MySQL到底有没有解决幻读问题?这篇文章彻底给你解答
MySQL InnoDB引擎在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题?
网上众说纷纭,有的说解决了,有的说没解决,甚至有些大v的意见都无法达成统一。
今天就深入剖析一下,彻底解决这个幻读的问题。
解决幻读问题之前,先普及几个知识点。
1. 并发事务产生的问题
先创建一张用户表,用作数据验证:
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(100) DEFAULT NULL COMMENT '姓名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='用户表';
并发事务会产生下面三个问题:
脏读
定义: 一个事务读到其他事务未提交的数据。
从上面的示例图中,可以看出,在事务2修改完数据,没有提交的情况。事务1已经读到事务2最新修改的数据,这种情况就属于脏读。
不可重复读
定义: 一个事务读取到其他事务修改过的数据。
从上面的示例图中,可以看出,在事务2修改完数据,并提交事务后。事务1第二次查询已经读到事务2最新修改的数据,这种情况就属于不可重复读。
幻读
定义: 一个事务读取到其他事务最新插入的数据。
从上面的示例图中,可以看出,在事务2插入完数据,并提交事务后。事务1第二次查询已经读到事务2最新插入的数据,这种情况就属于幻读。
2. 快照读和当前读
再普及一下快照读和当前读。
快照读: 读取数据的历史版本,不对数据加锁。
例如:select
当前读: 读取数据的最新版本,并对数据进行加锁。
例如:insert、update、delete、select for update、select lock in share mode。
3. 再谈幻读问题
MySQL在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题?
只能说是部分解决了幻读问题。
首先,在快照读的情况下,是通过MVCC(复用读视图)解决了幻读问题。
想详细了解MVCC和读视图,可以翻一下上篇文章。
先手动设置一下MySQL的隔离级别为可重复读:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
执行测试用例,验证一下:
从上面的示例图中,可以看出,事务1的两次查询,得到的结果一致,并没有查到事务2最新插入的数据。
原因是,在可重复读隔离级别下,第一次快照读的时候,生成了一个读视图。第二次快照读的时候,复用了第一次生成的读视图,所以两次查询得到的结果一致。
所以,在快照读的情况下,可重复读隔离级别是解决了幻读的问题。
再测试一下,在当前读的情况下,可重复读隔离级别是否解决幻读问题:
从上面的示例图中,可以看出,事务1的两次查询,得到的结果不一致。在事务2插入数据,并提交事务后。事务1的第二次执行当前读(加了for update)的时候,读到了事务2最新插入的数据。
原因是,在可重复读隔离级别下,每次执行当前读会生成一个新的读视图,所以能读到其他事务最新插入的数据。
所以,在当前读的情况下,可重复读隔离级别是没有解决了幻读的问题。
在执行上面的测试用例的时候,我忽然想到一个问题,既然select for update的当前读,出现了幻读问题,是不是其他的当前读也会复现幻读问题,比如insert。
再执行测试用例,验证一下:
跟预想的一样,在insert当前读的情况下,也出现了幻读的问题(主键冲突)。
那有没有什么办法?在可重复读隔离级别下,执行当前读的时候,也能解决幻读的问题?
当然有的,唯一的办法就是加锁。
事务1在执行第一次查询的时候,就对数据进行加锁(使用for update),防止其他事务修改数据,这样也就彻底解决了幻读问题。
你觉得有什么好办法吗?
MySQL到底有没有解决幻读问题?这篇文章彻底给你解答的更多相关文章
- MySQL 到底是怎么解决幻读的?
; 原理:将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的. 2. next-key 锁 (当前读) next-key 锁包含两部分: 记录锁(行锁) 间隙锁 记录锁是加在 ...
- MySQL到底能否解决幻读问题
先说结论,MySQL 存储引擎 InnoDB 在可重复读(RR)隔离级别下是解决了幻读问题的. 方法:是通过next-key lock在当前读事务开启时,1.给涉及到的行加写锁(行锁)防止写操作:2. ...
- MySQL 是如何解决幻读的
MySQL 是如何解决幻读的 一.什么是幻读 在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读. 而多出来或者少的哪一行被叫做 幻行 二.为什么要解决幻读 在高并发数据库系统中,需要保证 ...
- MySQL的可重复读级别能解决幻读吗
引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...
- MYSQL如何解决幻读
第一部分 首先要了解下mysql数据库的事务特征之一隔离级别: READ UNCOMMITTED(未提交读): 在READUNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的 ...
- 何为幻读?MySQL又是如何解决幻读的?
一.什么是幻读 在一次事务里面,多次查询之后,查询的结果集的个数不一致的情况叫做幻读.而多出来或者少的哪一行被叫做 幻行 二.为什么要解决幻读 在高并发数据库系统中,需要保证事务与事务之间的隔离性,还 ...
- 【大厂面试03期】MySQL是怎么解决幻读问题的?
问题分析 首先幻读是什么? 根据MySQL文档上面的定义 The so-called phantom problem occurs within a transaction when the same ...
- MySQL锁(三)行锁:幻读是什么?如何解决幻读?
概述 前面两篇文章介绍了MySQL的全局锁和表级锁,今天就介绍一下MySQL的行锁. MySQL的行锁是各个引擎内部实现的,不是所有的引擎支持行锁,例如MyISAM就不支持行锁. 不支持行锁就意味着在 ...
- MySQL的可重复读级别能解决幻读问题吗?
之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于幻读, ...
随机推荐
- this关键字、static关键字、方法的调用
1.带有static关键字的方法,不可使用this关键字.因为其调用方法为类名.方法名(建议这种方式,调用不需要对象的参与),不存在对象. 2.实例方法调用必须有对象的存在,先创建对象,通过引用.的方 ...
- SpringBoot项目启动org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException解决方法
将Pom文件中的SpringBoot版本调低即可. 我的是调成了2.5.6
- 基于NCF的多模块协同实例
简介 这次给大家带来的内容是基于NCF的多模块协同实例 主要讲解的内容是NCF的模块Xncf之间相互调用,相互协作的能力 这里可以把Xncf比作乐高玩具,一个Xncf就是你拥有的乐高玩具的类型,比如你 ...
- chrome请求cgi遇到net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
测试一个web demo的时候,通过chrome请求板子上的web server的cgi时总是提示:net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK) 搜遍整个 ...
- JDK9对集合添加的优化of方法和Debug追踪
JDK9对集合添加的优化(of方法) JDK9的新特性: 1.List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素 2.static List of (E- ...
- C# 实例解释面向对象编程中的接口隔离原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- e.printStackTrace() 原理的分析
e.printStackTrace(); 先查看下源码 如图片中1所示,使用的是 PrintStreamOrWriter public void printStackTrace() { printSt ...
- springmvc源码笔记-HandlerMethodReturnValueHandler
返回值解析器 用于对controller的返回值进行二次处理 结构 // 返回值解析器 public interface HandlerMethodReturnValueHandler { // 判断 ...
- 2522-Shiro系列--使用缓存对认证session和授权Cache进行存储
如何进行session的缓存? 原理: Shiro有1个类,AuthorizingRealm AuthenticatingRealm,里面有个获取认证信息的方法, AuthenticatingReal ...
- 「SDOI2016」征途 题解
「SDOI2016」征途 先浅浅复制一个方差 显然dp,可以搞一个 \(dp[i][j]\)为前i段路程j天到达的最小方差 开始暴力转移 \(dp[i][j]=min(dp[k][j-1]+?)(j- ...