MqSQL中的《快照读》和《当前读》

目录

1、MySQL读取定义

1.1、锁的分类

1.2、快照读与当前读

1.3、使用场景

1.4、区别

2、实现机制

2.1、实现原理

2.2、隔离级别和快照联系

1、隔离级别

2、快照读

2.3、快照何时生成

3、SQL场景实现

3.1、快照读

3.2、当前读

4、锁的细节(与当前读相关)

5、影响 / 并发行为

5.1、快照读:

5.2、当前读:

6、注意事项与常见误区


前言

        MySQL读取(主要指 InnoDB 存储引擎)中“快照读(snapshot read,也叫一致性读/consistent read)”和“当前读(current read)”。

如下所示:

        这两种读取方式在事务隔离级别、并发控制和数据一致性方面有着本质的区别。主要区别在于是否加锁以及数据一致性。


1、MySQL读取定义

1.1、锁的分类

1、共享锁(S锁):

   共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。

        如果事务T仅对数据A进行读取,那么会对数据A加上共享锁,之后则其他事务如果要读取数据A的话可以对其继续加共享锁,但是不能加排他锁(也就是无法修改数据)。获准共享锁的事务只能读数据,不能修改数据。

2、排他锁(X锁):

        用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。

        如果事务T对数据A要进行修改,则需要对其添加排它锁,加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据

SQL代码示例:

 共享锁
select * from table id = 1 lock in share mode;排他锁
select * from table where id = 1 for update;

1.2、快照读与当前读

1、快照读

        (Snapshot Read / Consistent Read)基于事务快照(MVCC),读取的是“某个时间点”的已提交版本,不加锁、非阻塞,多个读返回一致的历史版本。

 REPEATABLE READ 下(基于事务开始时的快照):同一事务内多次 SELECT 返回相同结果;

 READ COMMITTED 下每个语句建立新的快照。

SQL示例如下:

-- 事务 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1; -- 快照读,读取事务开始时的数据-- 事务 B
START TRANSACTION;
UPDATE users SET name = 'Alice' WHERE id = 1; -- 更新数据并提交
COMMIT;-- 事务 A
SELECT * FROM users WHERE id = 1; -- 仍然读取事务开始时的数据(快照读)
COMMIT;

2、当前读

        (Current Read):直接读取当前最新数据(buffer pool/磁盘)并且读取之后还要保证其他并发事务不能修改当前记录,对读取的记录加锁。

当前读:select…lock in share mode,select…for update。

当前读:update,delete,insert。

SQL代码示例如下:

-- 事务 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE; -- 当前读,获取最新数据并加锁-- 事务 B
START TRANSACTION;
UPDATE users SET name = 'Alice' WHERE id = 1; -- 被阻塞,等待事务 A 释放锁-- 事务 A
COMMIT; -- 提交后,事务 B 的更新操作继续执行

1.3、使用场景

1、当前读适用场景

  1. 需要获取最新数据的实时查询
  2. 需要保证数据一致性的金融交易
  3. 先读后写的业务逻辑
  4. 需要防止并发修改的场景

2、快照读适用场景

  1. 只读查询(报表、数据分析)
  2. 对实时性要求不高的查询
  3. 大查询,不希望阻塞其他操作
  4. 需要高并发的读场景

1.4、区别

如下所示:


2、实现机制

2.1、实现原理

1、快照读:通过MVCC+undolog实现;

        如果最新版本不是当前事务可见,InnoDB 会从 undo log 找到符合快照时间点的版本(所以快照读可能读取 undo 中的旧版本)。不会设置锁。

        不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,既链表,undo log的链首就是最新的旧记录,链尾就是最早的旧记录。

        所以快照读都是去读取undolog中链首的最新的旧记录。

更多mvcc和undolog的介绍,可参考:探讨LRU和MVCC在场景的实践-CSDN博客文章浏览阅读827次,点赞33次,收藏29次。MVCC 可以有效防止脏读,因为它提供一致的快照显示已提交修改的数据。它通过版本控制和快照隔离处理多用户并发访问,从而提高数据库的高并发性能。1、彻底拿下InnoDB的MVCC快照机制_innodb 的 快照读 如何提取快照-CSDN博客。 https://dyclt.blog.csdn.net/article/details/147588118?spm=1011.2415.3001.5331

2、当前读:通过共享锁+排他锁+Next-Key Lock实现;

当前读通过next-key锁(记录锁+间隙锁)来实现:行锁(Record Lock):锁定索引记录
间隙锁(Gap Lock):锁定索引记录之间的间隙
next-key锁:行锁+间隙锁,锁定一个范围并锁定记录本身
例如执行DELETE FROM T WHERE age = 7;时,MySQL会在age索引上加锁(4,10)区间,防止其他事务
插入age=7的记录,从而避免幻读问题。

如下所示:

  1. 每次对行数据进行读取的时候,加共享锁。此时就不允许修改,但是允许其他事务读取,所以每次都可以读到最新的数据。
  2. 每次对行数据进行修改的时候,加排他锁,不允许其他事务读取和修改。这种情况下其他事务读取的数据也一定是最新的数据。
  3. 每次对范围行数据进行读取的时候,对这个范围加一个范围共享锁
  4. 每次对范围行数据进行修改的时候,读这个范围加一个范围排它锁。
  5. 基于上述锁机制,实现当前读,确保每次读取的都是最新的数据。

⚠️注意:

        next-key包括两部分:行锁间隙锁。行锁是加在索引上的锁(而非数据行),间隙锁是加在索引之间的。

2.2、隔离级别和快照联系

1、隔离级别

1、读未提交(READ UNCOMMITTED)

快照读:不存在,总是读取最新数据(包括未提交的)。

当前读:读取最新已提交数据并加锁。

2、读已提交(READ COMMITTED)

快照读:每次SELECT都会生成新的ReadView,读取最新已提交数据。

当前读:读取最新已提交数据并加锁。

3、可重复读(REPEATABLE READ)

快照读:事务第一次SELECT时生成ReadView,后续复用,保证读取一致性。

当前读:读取最新已提交数据并加锁。

4、串行化(SERIALIZABLE)

快照读:退化为当前读(加共享锁)。

当前读:读取最新已提交数据并加锁。

2、快照读

REPEATABLE READ(默认):

        事务开始时建立一次快照,整个事务内普通 SELECT 都基于这个快照(repeatable)。

READ COMMITTED:

        每个语句单独建立快照(statement-level),因此同一事务内不同语句可能看到不同已提交数据(避免脏读,但允许不可重复读)。

Undo log 提供历史版本;如果旧版本被 purge 掉,读取老快照可能失败。

2.3、快照何时生成

1、在读未提交隔离级别下,快照是什么时候生成的?

没有快照,因为不需要,怎么读都读到最新的,不管是否提交。

2、在读已提交隔离级别下,快照是什么时候生成的?

SQL语句开始执行的时候。

3、在可重复读隔离级别下,快照是什么时候生成的?

        事务开始的时候(可能会有很多条select SQL语句执行,快照生命周期是到事务结束的时候)

4、在串行化隔离级别下,快照是什么时候生成的?

“写”会加“写锁”,“读”会加“读锁”,读的的数据都是当前最新的数据(没有快照,当前读)


3、SQL场景实现

3.1、快照读

1、 快照读不会看到后续提交(REPEATABLE READ):事务级快照读

事务 T1:

BEGIN;       SELECT value FROM t WHERE id=1; 

-- 假设值为 A (从快照读)(此时 T1 未提交,继续执行)

事务 T2:

BEGIN;       UPDATE t SET value='B' WHERE id=1;        COMMIT;

回到 T1:在 REPEATABLE READ 下仍然看到 A(快照不变)

SELECT value FROM t WHERE id=1;   

COMMIT;

2、 READ COMMITTED 下快照行为(每语句快照):语句级快照读

事务 T1:

BEGIN;     SELECT value FROM t WHERE id=1;

-- 看到 A

事务 T2:

BEGIN;       UPDATE t SET value='B' WHERE id=1;        COMMIT;

T1 再次执行:

SELECT value FROM t WHERE id=1;

-- 在 READ COMMITTED 下可能看到 B(新的语句快照)

3.2、当前读

1、当前读会立即看到并与写冲突/加锁:

事务 T1:

BEGIN;        SELECT value FROM t WHERE id=1 FOR UPDATE;

-- 当前读并对该行加排它锁(此时 T1 锁住该行)

事务 T2(并发执行):

BEGIN;   UPDATE t SET value='B' WHERE id=1;       COMMIT;

-- 将在 T1 提交前被阻塞,直到 T1 提交或回滚


4、锁的细节(与当前读相关)

更多关于mysql的锁介绍:MySQL的事务和锁机制的详细介绍_mysql锁机制与事物-CSDN博客文章浏览阅读1.3k次,点赞47次,收藏10次。MySQL事务与锁机制详解 摘要: 本文详细解析MySQL的事务特性和锁机制。首先介绍事务的ACID特性(原子性、一致性、隔离性、持久性)和四种隔离级别(读未提交、读提交、可重复读、串行化),重点分析多线程并发事务可能产生的脏读、不可重复读和幻读问题。其次深入探讨MVCC多版本并发控制原理及其解决并发问题的方式。然后系统讲解MySQL锁的分类,包括独占锁、共享锁及其兼容性,以及InnoDB引擎特有的记录锁、间隙锁、临键锁等实现细节。最后提供锁监控方法和优化建议,包括缩短事务长度、合理设计索引等,并比较不同隔_mysql锁机制与事物 https://dyclt.blog.csdn.net/article/details/149141972?spm=1011.2415.3001.5331

1、SELECT ... FOR UPDATE:

        对选中的记录加排它锁(record lock),在 REPEATABLE READ 下通常是 next‑key lock(record+gap),能防幻读;在 READ COMMITTED 下可能只加 record lock(实现差异)。

2、SELECT ... LOCK IN SHARE MODE:

共享锁,允许并发读取但阻止写入。

UPDATE/DELETE 语句本质是当前读(读取并锁定匹配行),而非快照读。


5、影响 / 并发行为

5.1、快照读:

不阻塞其他事务的写操作(不会加锁)。

不被子后续提交所影响(在 REPEATABLE READ 内)不会阻塞写者,但写者提交不会让已存在事务的快照变更。

5.2、当前读:

会加锁,可能阻塞其他事务(或被其他事务阻塞),用于实现悲观锁定和防止幻读/并发冲突。SELECT ... FOR UPDATE 会锁定读取到的记录(并可能使用 next-key lock 以避免幻读,取决于隔离级别和索引类型)。


6、注意事项与常见误区

1、 “快照读不会造成任何索引访问” 不准确:

        快照读也会走索引来定位行,但读取逻辑是基于版本可见性(从 undo 中回溯),它不设置锁。

2、长事务会保留较多 undo 数据:

影响 undo log 大小并增加 purge 压力;长时间的快照读(长事务)会阻止旧版本被清理。

3、不稳定结果

        与快照/当前读无直接关系,但与隔离级别和锁有关,使用 skip/limit 的分页在并发写入下可能产生。


总结

        普通 SELECT(无 FOR UPDATE/LOCK)是快照读(基于 MVCC,非锁定),在 REPEATABLE READ 下为事务级快照,同一事务内多次 SELECT 返回一致结果;READ COMMITTED 下每语句建立快照。

        SELECT ... FOR UPDATE / UPDATE / DELETE 等是当前读,会读取最新数据并加锁,可能阻塞其他事务写入。

        选择隔离级别与是否加锁,需要在“数据一致性需求(可重复读/防止幻读)”与“并发性能(锁竞争/阻塞)”之间权衡。


参考文章:

1、Mysql中的快照读和当前读_mysql快照读-CSDN博客文章浏览阅读1k次,点赞9次,收藏10次。本文介绍了MySQL的两种读取模式:当前读和快照读。当前读通过共享锁、排他锁和Next - Key Lock实现,每次读取最新数据;快照读通过MVCC和undolog实现,读写不冲突。还阐述了相关知识,如undolog、共享锁和排他锁,并分析了不同隔离级别下快照读的差异。 https://blog.csdn.net/aberwang9/article/details/135185331?ops_request_misc=&request_id=&biz_id=102&utm_term=mysql%E7%9A%84%E5%BD%93%E5%89%8D%E8%AF%BB%E5%92%8C%E5%BF%AB%E7%85%A7%E8%AF%BB&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-135185331.142^v102^control&spm=1018.2226.3001.4187

2、【MYSQL】当前读和快照读_mysql 当前读-CSDN博客文章浏览阅读821次,点赞3次,收藏9次。复习下隔离级别:1、读未提交:一个事务还没提交时,它做的变更就能被别的事务看到。2、读提交:一个事务提交之后,它做的变更会被其他事务看到3、可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交的数据对其他事务不可见4、串行化:对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。_mysql 当前读 https://blog.csdn.net/xiazi0721/article/details/141175805?ops_request_misc=&request_id=&biz_id=102&utm_term=mysql%E7%9A%84%E5%BD%93%E5%89%8D%E8%AF%BB%E5%92%8C%E5%BF%AB%E7%85%A7%E8%AF%BB&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-141175805.142^v102^control&spm=1018.2226.3001.4187

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

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

相关文章

【Docker项目实战】使用Docker部署Notepad轻量级记事本

【Docker项目实战】使用Docker部署Notepad轻量级记事本一、 Notepad介绍1.1 Notepad简介1.2 Notepad特点1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载Note…

开疆智能ModbusTCP转Ethernet网关连接FBOX串口服务器配置案例

本案例是串口服务器通过串口采集第三方设备数据转成ModbusTCP的服务器后欧姆龙PLC通过Ethernet连接到网关,读取采集到的数据。具体配置过程如下。配置过程:Fbox做从站FBox采集PLC数据,通过Modbus TCP Server/Modbus RTU Server协议配置地址映…

Vue中的数据渲染【4】

目录1.页面样式绑定:1.概述: 2.绑定方式:1.通过类名绑定:1.通过动态类名绑定:(:class)2.通过类名数组绑定:3.通过类名对象进行绑定:2.内联样式绑定&#xff1…

LeeCode 39.组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限制重复被选取 。如果…

基于Python3.10.6与jieba库的中文分词模型接口在Windows Server 2022上的实现与部署教程

该教程详细阐述了在Windows Server 2022上基于Python3.10.6与jieba库实现并部署中文分词模型接口的完整流程,涵盖技术栈(Python3.10.6、jieba、Flask、Waitress、Nginx、NSSM等)与环境准备(Python安装、虚拟环境配置、依赖包安装及…

java基础(九)sql基础及索引

一、NoSQL 和 SQL 数据库的区别1. 基本概念SQL 数据库(关系型数据库) 代表产品:SQL Server, Oracle, MySQL (开源), PostgreSQL (开源)。 存储方式:结构化数据,逻辑上以二维表(行 & 列)形式…

ffmpeg-调整视频分辨率

ffmpeg -i input.mp4 -vf scale1280:720 output_1280x720.mp4-i input.mp4: 指定输入视频文件。-vf scale1280:720: 使用 scale 视频滤镜,将视频宽度设置为 1280 像素,高度设置为 720 像素。output_1280x720.mp4: 指定输出视频文件。 16:9 常…

前端vue3+后端spring boot导出数据

有个项目需要提供数据导出功能。 该项目前端用vue3编写,后端是spring boot 2,数据库是mysql8。 工作流程是:1)前端请求数据导出 2)后端接到请求后,开启一个数据导出线程,然后立刻返回信息到前端…

基于RK3588的微电网协调控制器:实现分布式能源的智能调控与优化运行

微电网协调控制器方案通过集成先进算法和实时数据技术,实现分布式能源的光伏、储能、风电等设备的智能协调与优化运行‌12。关键功能包括:‌协同优化调度‌:采用模型预测控制(MPC)动态调整光伏出力、储能充放电策略和负…

机器学习——TF-IDF文本特征提取评估权重 + Jieba 库进行分词(以《红楼梦》为例)

使用 Jieba 库进行 TF-IDF 关键词提取(以《红楼梦》为例)在中文文本分析中,TF-IDF(Term Frequency - Inverse Document Frequency) 是最常用的关键词提取方法之一。它通过评估词在单个文档中的出现频率和在所有文档中的…

一周学会Matplotlib3 Python 数据可视化-多子图及布局实现

锋哥原创的Matplotlib3 Python数据可视化视频教程: 2026版 Matplotlib3 Python 数据可视化 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程讲解利用python进行数据可视化 科研绘图-Matplotlib,学习Matplotlib图形参数基本设置&…

Spark执行计划与UI分析

文章目录1.Spark任务阶段划分1.1 job,stage与task1.2 job划分1.3 stage和task划分2.任务执行时机3.task内部数据存储与流动4.根据sparkUI了解Spark执行计划4.1查看job和stage4.2 查看DAG图4.3查看task1.Spark任务阶段划分 1.1 job,stage与task 首先根据…

16-docker的容器监控方案-prometheus实战篇

文章目录一.前置知识1.监控与报警2.监控系统的设计3.监控系统的分类二、prometheus概述1.什么是prometheus2.prometheus的历史3.为什么要学习prometheus4.prometheus的使用场景5.prometheus的宏观架构图6.prometheus软件下载地址三、部署prometheus server监控软件1.同步集群时…

集成电路学习:什么是Image Processing图像处理

Image Processing,即图像处理,是计算机视觉、人工智能、多媒体等领域的重要基础。它利用计算机对图像进行分析、加工和处理,以达到预期目的的技术。以下是对图像处理的详细解析: 一、定义与分类 定义: 图像处理是指用计算机对图像进行分析,以达到所需结果的技术,又称…

基于Android的随身小管家APP的设计与实现/基于SSM框架的财务管理系统/android Studio/java/原生开发

基于Android的随身小管家APP的设计与实现/基于SSM框架/android Studio/java/原生开发

Web 开发 16

1 在 JavaScript(包括 JSX)中,函数体的写法和返回值处理在 JavaScript(包括 JSX)中,函数体的写法和返回值处理确实有一些简洁的语法规则,尤其是在箭头函数中。这些规则常常让人混淆,…

超高车辆碰撞预警系统如何帮助提升城市立交隧道安全?

超高车辆带来的安全隐患立交桥和隧道的设计通常基于常规车辆的高度标准。然而,随着重型运输业和超高货车的增加,很多超高车辆会误入这些限高区域,造成潜在的安全隐患。超高车辆与立交桥梁或隧道顶盖发生碰撞时,可能导致结构受损&a…

三种变量类型在局部与全局作用域的区别

一、基本概念作用域(Scope): 全局作用域:定义在所有函数外部的变量或函数,具有文件作用域,生命周期为整个程序运行期间。局部作用域:定义在函数、块(如 {})或类内部的变量…

InfluxDB 数据迁移工具:跨数据库同步方案(二)

六、基于 API 的同步方案实战6.1 API 原理介绍InfluxDB 提供的 HTTP API 是实现数据迁移的重要途径。通过这个 API,我们可以向 InfluxDB 发送 HTTP 请求,以实现数据的读取和写入操作。在数据读取方面,使用GET请求,通过指定数据库名…

JVM安全点轮询汇编函数解析

OpenJDK 17 源码的实现逻辑,handle_polling_page_exception 函数在方法返回时的调用流程如下:调用流程分析:栈水印检查触发跳转:当线程执行方法返回前的安全点轮询时(MacroAssembler::safepoint_poll 中 at_returntrue…