可重复读为什么能避免一部分幻读,但是没能完全避免幻读

事物的隔离级别已经介绍过了,接下来我们谈谈细节部分。
MySQL innoDB引擎的默认隔离级别——可重复读
虽然可重复读不能完全避免幻读,但其实已经避免了很大一部分了。具体怎么做的呢,主要有以下两个操作:

  • 针对快照读,是通过MVCC(多版本并发控制)方式解决了幻读。意思就是说事务开始后,执行第一个查询语句时,会创建一个 Read View(快照),后续查询的结果都是根据根据这个快照得出的。这个快照是根据undo log 版本链实现的,后续会说。
  • 针对当前读,是通过next-key lock(记录锁+间隙锁)方式解决了幻读。需要注意的是,快照读仅针对普通的select查询。假设事务想执行update、insert、delete,就得先去看当前最新的数据是什么样的,这就是当前读。否则你想update,但是其他事务delete了并且提交了,那这逻辑就冲突了。所以其实有一种特殊的查询语句select … for update,区别于普通的select查询,这种查询语句是当前读。但这就出现了幻读,如下图:
    在这里插入图片描述
    所以,为了解决幻读问题,select … for update有一种机制叫做next-key lock(间隙锁+记录锁)+在这里插入图片描述

注意区间是 ( 2 , + ∞ ] (2, +\infty] (2,+],为什么呢,因为next-key lock是间隙锁(gap lock,锁住一个左开右开的开区间,阻止插入)和记录锁(record lock,也称行锁,只锁住一行,阻止删除更新)的合体。

但是为啥说这俩机制没完全解决幻读呢?主要是以下两种情况没法避免
情况一

# 事务 A
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from t_stu where id = 5;
Empty set (0.01 sec)
# 事务 B
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> insert into t_stu values(5, '小美', 18);
Query OK, 1 row affected (0.00 sec)mysql> commit;
Query OK, 0 rows affected (0.00 sec)

我们会发现,A事务其实没主动插入id=5的数据,是B事务插入并且提交的,A数据想要执行update就不能用快照,得用当前数据的版本,所以就把B的数据读出来了,然后就给更新了。所以MVCC是不能完全避免幻读的。

# 事务 A
mysql> update t_stu set name = '小林coding' where id = 5;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from t_stu where id = 5;
+----+--------------+------+
| id | name         | age  |
+----+--------------+------+
|  5 | 小林coding   |   18 |
+----+--------------+------+
1 row in set (0.00 sec)

情况二

  • T1 时刻:事务 A 先执行「快照读语句」:select * from t_test where id > 100 得到了 3 条记录;
  • T2 时刻:事务 B 往插入一个 id= 200 的记录并提交;
  • T3 时刻:事务 A 再执行「当前读语句」 select * from
    t_test where id > 100 for update 就会得到 4 条记录,此时也发生了幻读现象。
    这个现象是因为没能早点锁住记录,所以尽量在开启事务之后,马上执行 select … for update 这类当前读的语句,从而避免其他事务插入一条新记录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/230713.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

速记:一个保险丝检测电路

一个保险丝检测电路 保险丝熔断:红灯亮 保险丝正常:绿灯亮 同样的,仿真中的指示灯可以换成其他指示器件。

AMQ基础

一、消息中间件模式分部 queue  一对一。实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。 topic  一…

优化邮件群发效果的方法与策略

怎样优化邮件群发效果?这是许多企业在进行邮件营销时常常被问到的问题。邮件营销是一种高效且经济实惠的市场推广方式,但如何使邮件真正引起接收者的兴趣并产生预期的效果并不容易。好的营销效果可以带来高回报、高收益率,但是怎么提升群发效…

Chrome显示分享按钮

分享按钮不见了! Chrome://flags Chrome Refresh 2023 Disabled 左上角的标签搜索会到右上角。

文件重命名:如何删除文件名中的下划线,特殊符号批量删除

在日常的工作中,经常会遇到文件名中包含特殊符号的情况,例如,一些文件名可能包含下划线、空格或其他特殊符号,这些符号可能会干扰我们的文件搜索和识别。此外,一些文件名可能包含无法识别的非标准字符,这可…

RT-DETR算法优化改进:AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv | 2023年11月最新发表

💡💡💡本文全网首发独家改进:可改变核卷积(AKConv),赋予卷积核任意数量的参数和任意采样形状,为网络开销和性能之间的权衡提供更丰富的选择,解决具有固定样本形状和正方形的卷积核不能很好地适应不断变化的目标的问题点,效果秒殺DSConv 1)AKConv替代标准卷积进行…

纵行科技获评“汽车物流行业优秀技术装备供应商”

近日,由中国物流与采购联合会主办,中物联汽车物流分会承办的“2023年全国汽车物流行业年会”在湖北十堰盛大召开。本次年会集合了汽车整车、零部件、售后备件、进出口物流企业和物流装备技术企业、科研机构及院校等,分享汽车物流行业现状、相…

ArkTS-ohpm控制台无法使用

ohpm : 无法将“ohpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 ohpm install ohos/axiosCategoryInfo : ObjectNotFound: (ohpm:String) […

C语言进阶指南(16)(自定义数据类型——结构体)

欢迎来到博主的专栏——C语言进阶指南 博主id:reverie.ly 文章目录 结构体类型结构体类型的声明结构体变量的声明 结构体变量的初始化结构体变量结构体变量的赋值结构体变量的成员结构体变量的使用结构体变量的内存存储 前面使用的变量都是简单类型的变量&#xff0…

wvp 视频监控平台抓包分析

抓包时机 下面的抓包时机是抓包文件最新,但是最有用的包 选择网卡开始抓包 如果之前已经选择网卡,直接开始抓包 停止抓包 重新抓包 sip播放过程分析 过滤条件 tcp.port 5060 and sip 可以看到有这些包 选择任何一个 ,戍边右键--追踪流--…

操作系统 day14(进程同步、进程互斥、互斥的代码实现、互斥的硬件实现、互斥锁)

进程同步 概念 进程的异步性体现在,例如:当有I/O操作时,进程需要等待I/O操作,而每个I/O操作又是不同的,所以进程没有一个固定的顺序,固定的时间来执行,而这体现了进程的异步性。 进程互斥 …

【LeetCode:907. 子数组的最小值之和 | 贡献法 乘法原理 单调栈】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…