解决MySQL幻读?可重复读隔离级别背后的工作原理

什么是当前读和快照读

  1. 当前读:又称为 "锁定读",它会读取记录的最新版本(也就是最新的提交结果),并对读取到的数据加锁,其它事务不能修改这些数据,直到当前事务提交或回滚。"select … for update" 和 "update"、"delete"、"insert" 这类修改数据的语句都属于当前读。

  2. 快照读:又称为 "一致性读",它会读取记录在事务开始时的版本,也就是它会读取一个快照。"select" 语句一般就是快照读。

MySQL 可重复读隔离级别(RR)

在MySQL可重复读事务隔离级别下可以解决大部分幻读问题,而不是全部幻读问题。如果一个事务在执行过程中既有快照读又有当前读就会发生幻读问题。

在 MySQL 中,默认的事务隔离级别是 “可重复读(RR)”。
如何查询当前事务隔离级别?

SELECT @@transaction_isolation;

COPY

file

在可重复读(RR)隔离级别下,同一个事务中的快照读取同样的记录时,总是能够得到同样的结果,但是无法防止其他事务在此期间插入新的行(新增数据),这种现象被称为幻读。MySQL RR隔离级别下会使用MVVC和Next-Key Lock来防止幻读。

下面的示例展示了幻读现象:
整体逻辑为:

事务A事务B
开启事务,查询数量大于10的订单,此时只能查到2条记录,因为此时另一个事务还没有进行插入,sql语句:SELECT * FROM trade_order WHERE quantity > 10;快照读) !

file

事务B启动并插入一条数量为30的订单并提交事务。SQL语句:INSERT INTO trade_order (item, quantity) VALUES ('pear', 30); 

file

事务A再次执行查询数量大于10的订单,依然只有2条,因为是快照读。sql语句:SELECT * FROM trade_order WHERE quantity > 10;

file

事务A执行快照读,这时候查询到了3条发生幻读,SQL语句:SELECT * FROM trade_order WHERE quantity > 10 for update;(*当前读) 

file

假设我们有一个包含以下数据的 "trade_order" 表:


CREATE TABLE trade_order (id INT PRIMARY KEY AUTO_INCREMENT,item VARCHAR(100),quantity INT
);
-- 插入3条数据,两条数量大于10,一条小于等于10
INSERT INTO trade_order (item, quantity) VALUES
('apple', 10),
('banana', 20),
('cherry', 15);## 事务SQL执行步骤
注意: SQL在两个命令行窗口下执行,目前Windows Powershell可以很容易安装MySQL客户端,所以可以新建两个PowerShell窗口来执行。
```sql
-- Transaction A
START TRANSACTION;
-- 查询 quantity > 10 的记录。因为是快照读,它会读取该事务开始时的记录快照
SELECT * FROM trade_order WHERE quantity > 10;
-- +----+--------+----------+
-- | id | item   | quantity |
-- +----+--------+----------+
-- | 21 | banana |       20 |
-- | 22 | cherry |       15 |
-- +----+--------+----------+
-- 2 rows in set (0.00 sec)-- Transaction B
START TRANSACTION;
-- 插入一条新的记录,quantity > 10
INSERT INTO trade_order (item, quantity) VALUES ('pear', 30);
COMMIT;-- Transaction A
-- 再次查询 quantity > 10 的记录。因为是快照读,它会读取该事务开始时的记录快照
SELECT * FROM trade_order WHERE quantity > 10;
-- +----+--------+----------+
-- | id | item   | quantity |
-- +----+--------+----------+
-- | 21 | banana |       20 |
-- | 22 | cherry |       15 |
-- +----+--------+----------+
-- 2 rows in set (0.00 sec)-- 再次执行当前读取操作(记录最新的数据,并对这些记录加锁)
SELECT * FROM trade_order WHERE quantity > 10 FOR UPDATE;-- +----+--------+----------+
-- | id | item   | quantity |
-- +----+--------+----------+
-- | 21 | banana |       20 |
-- | 22 | cherry |       15 |
-- | 23 | pear   |       30 |
-- +----+--------+----------+
-- 3 rows in set (3.79 sec)
-- 这就是幻读问题,因为这次查询返回了比之前更多的行。COMMIT;

COPY

所以说,在可重复读隔离级别下,MySQL 通过使用快照读(MVCC,多版本并发控制)确保了在一个事务里多次读取同样的记录能得到一致的结果,但是对于新增的行,即出现在事务开始后的新行,就无法做到一致性读取,这种现象被称为“幻读”。

结语

在大多数情况下,MySQL的可重复读(RR)事务隔离级别为绝大多数业务场景提供了适当的一致性保证,并有效地通过MVCC和Next-Key Locks机制解决了幻读问题。尽管如此,RR隔离级别可能会由于锁机制而导致某些性能问题,特别是在密集型的写操作或高并发场景时。

如果业务需求对数据的实时一致性要求不是特别严格或者你可以在应用层处理这些问题,并且更加关注于系统性能,可以考虑将事务隔离级别降低到读提交(RC)。读提交隔离级别在某些情况下可以提供更高的并发性,因为它只在必要时锁定数据行,以此减少锁争用。但是在你切换到RC隔离级别时你得评估带来的问题:比如:不可重复读和幻读,别到时候应用各种问题。

参考

1. 快分清MySQL当前读、快照读和幻读关系 – FOF编程网

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

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

相关文章

每日刷题:Day1

Day1 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 目录 1. 58. 最后一个单词的长度 - 力扣(LeetCode) 2. 28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode&#x…

结构体,联合体,枚举( 2 )

目录 2.联合体 2.1联合体类型的声明 2.2联合体的特点 2.3联合体的内存大小 3.枚举 3.1枚举类型的声明 3.2枚举类型的优点 3.3枚举类型的使用 2.联合体 联合体(Union)是另一种复合数据类型,它允许我们在同一内存位置存储不同的数据类型…

Lumos学习王佩丰Excel第一讲:认识Excel

最近发现自己在操作excel的一些特殊功能时会有些不顺手,所以索性找了一个比较全的教程(王佩丰excel24讲)拿来学习,刚好形成文档笔记,分享给有需要但没有时间看视频的朋友们。整体笔记以王老师授课的知识点去记录&#…

嵌入式秋招项目(环境监测系统节点+云服务器+QT界面设计)

文章目录 1. 项目简介2. 项目文档与资源提供3. 项目实现效果 1. 项目简介 本项目实现的是环境监测系统,包括节点数据采集,云服务器部署,以及QT上位机界面设计,具体框图可见下图 节点端:采用STM32控制芯片,…

乐校园二手书交易管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)大学生闲置二手书在线销售

本项目包含可运行源码数据库LW,文末可获取本项目的所有资料。 推荐阅读300套最新项目持续更新中..... 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含ja…

013——超声波模块驱动开发(基于I.MX6uLL与SR04)

目录 一、 模块介绍 1.1 产品特色 1.2 产品实物图 1.3 接口定义 1.4 测距调节 1.5 模块工作原理 1.6 注意 二、 编码思路 三、 驱动程序 四、 应用程序 五、 Makefile 六、 其它及实验 一、 模块介绍 超声波测距模块是利用超声波来测距。模块先发送超声波&#xf…

五、postman基础使用案例

postman基础使用 相关案例【传递查询参数】【提交表单数据】【提交JSON数据】 注:postman⼀款⽀持调试和测试的⼯具,开发、测试⼯程师都可以使⽤。方法一般统一为:方法→请求头→请求体→断言 相关案例 【传递查询参数】 访问TPshop搜索商品的…

【零基础学数据结构】顺序表

目录 1.了解数据结构 什么是数据结构? 为什么要进行数据管理? 2.顺序表 顺序表概要解析: ​编辑顺序表的分类: 差别和使用优先度: 1.创建顺序表 1.1顺序表分为静态顺序表和动态顺序表 1.2顺序表的初始化…

certum泛域名ssl证书低至230元一年

Certum是一家国际知名的证书颁发机构,创建于欧洲,自1998年建立,几十年来每年都经过WebTrust审核,旗下的数字证书产品应用日益广泛。Certum旗下的数字证书类型丰富,而泛域名SSL证书是一种特殊的数字证书,它可…

Jenkins--任务详解

一、任务类型 Jenkins的主要功能的实现是由执行任务去完成的,常用的任务类型主要有以下三种: 自由风格任务(Free Style Project): 这是Jenkins中最常用的任务类型,允许你自定义各种构建步骤和配置选项,如源码管理、构建触发器、…

3.java openCV4.x 入门-数据类型(CvType)与Scalar

专栏简介 💒个人主页 📰专栏目录 点击上方查看更多内容 📖心灵鸡汤📖我们唯一拥有的就是今天,唯一能把握的也是今天 🧭文章导航🧭 ⬆️ 2.hello openCV ⬇️ 4.待更新 数据类型&#xff…

蓝牙BLE开发——如何实时监听蓝牙适配器状态变化及回调

uniapp 监听蓝牙适配器状态变化事件 近年来开发项目中接触比较多的与硬件设备对接,通过蓝牙与设备通讯;开发 App、微信小程序,今天分享其中如何监听蓝牙适配;近期比较忙,不定时更新,有时间会分享 uniapp开发…