当前位置: 首页 > news >正文

MySQL是如何解决幻读的

一、什么是幻读

在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行

二、为什么要解决幻读

在高并发数据库系统中,需要保证事务与事务之间的隔离性,还有事务本身的一致性。

三、MySQL 是如何解决幻读的

如果你看到了这篇文章,那么我会默认你了解了 脏读 、不可重复读与可重复读。

1. 多版本并发控制(MVCC)(快照读)

多数数据库都实现了多版本并发控制,并且都是靠保存数据快照来实现的。以 InnoDB 为例,每一行中都冗余了两个字段。一个是行的创建版本,一个是行的删除(过期)版本。版本号随着每次事务的开启自增。事务每次取数据的时候都会取创建版本小于当前事务版本的数据,以及过期版本大于当前版本的数据

普通的 select 就是快照读。

select * from T where number = 1;

原理:将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的。

2. next-key 锁 (当前读)

next-key 锁包含两部分

  1. 记录锁(行锁
  2. 间隙锁

记录锁是加在索引上的锁,间隙锁是加在索引之间的。(思考:如果列上没有索引会发生什么?)

select * from T where number = 1 for update;
select * from T where number = 1 lock in share mode;
insert
update
delete

原理:将当前数据行与上一条数据和下一条数据之间的间隙锁定,保证此范围内读取的数据是一致的。

其他:MySQL InnoDB 引擎 RR 隔离级别是否解决了幻读
引用一个 github 上面的评论 地址:

Mysql官方给出的幻读解释是:只要在一个事务中,第二次select多出了row就算幻读。
a事务先select,b事务insert确实会加一个gap锁,但是如果b事务commit,这个gap锁就会释放(释放后a事务可以随意dml操作),a事务再select出来的结果在MVCC下还和第一次select一样,接着a事务不加条件地update,这个update会作用在所有行上(包括b事务新加的),a事务再次select就会出现b事务中的新行,并且这个新行已经被update修改了,实测在RR级别下确实如此。

如果这样理解的话,Mysql的RR级别确实防不住幻读

有道友回复 地址:

在快照读读情况下,mysql通过mvcc来避免幻读。
在当前读读情况下,mysql通过next-key来避免幻读。
select * from t where a=1;属于快照读
select * from t where a=1 lock in share mode;属于当前读

不能把快照读和当前读得到的结果不一样这种情况认为是幻读,这是两种不同的使用。所以我认为mysql的rr级别是解决了幻读的。

先说结论,MySQL 存储引擎 InnoDB 隔离级别 RR 解决了幻读问题。

如引用一问题所说,T1 select 之后 update,会将 T2 中 insert 的数据一起更新,那么认为多出来一行,所以防不住幻读。看着说法无懈可击,但是其实是错误的,InnoDB 中设置了 快照读 和 当前读 两种模式,如果只有快照读,那么自然没有幻读问题,但是如果将语句提升到当前读,那么 T1 在 select 的时候需要用如下语法: select * from t for update (lock in share mode) 进入当前读,那么自然没有 T2 可以插入数据这一回事儿了。

注意
next-key 固然很好的解决了幻读问题,但是还是遵循一般的定律,隔离级别越高,并发越低。

以上所述是小编给大家介绍的MySQL是如何解决幻读的详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章:

  • Spark的三种运行模式快速入门
  • 主从复制原理
  • 绘制图片和文字
  • mysql日志中redo和undo日志概念以及应用
  • configure/make/make install的作用
  • MySQL索引
  • HDU 5019 Revenge of GCD(数学)
  • [<事务专题>]
  • Nginx总算支持动态模块了
  • 【MySQL中的锁】
  • Linux在线安装git(亲测成功)
  • [<MySQL优化总结>]
  • yum update
  • Redis是什么?
  • C语言中函数返回值的问题
  • hexo+github搭建个人博客
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【RocksDB】TransactionDB源码分析
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • CSS实用技巧干货
  • OSS Web直传 (文件图片)
  • Python利用正则抓取网页内容保存到本地
  • quasar-framework cnodejs社区
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Redis的resp协议
  • 阿里研究院入选中国企业智库系统影响力榜
  • 浮现式设计
  • 简单易用的leetcode开发测试工具(npm)
  • 今年的LC3大会没了?
  • 京东美团研发面经
  • 微信支付JSAPI,实测!终极方案
  • 仓管云——企业云erp功能有哪些?
  • ​香农与信息论三大定律
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #每日一题合集#牛客JZ23-JZ33
  • (1)虚拟机的安装与使用,linux系统安装
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (黑马C++)L06 重载与继承
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (转)C#调用WebService 基础
  • (转)程序员疫苗:代码注入
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .net 后台导出excel ,word
  • .NET/C# 使窗口永不获得焦点
  • .NET/C# 使用反射调用含 ref 或 out 参数的方法
  • .NET下的多线程编程—1-线程机制概述
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • /bin/bash^M: bad interpreter: No such file or directory
  • /etc/shadow字段详解
  • @column注解_MyBatis注解开发 -MyBatis(15)