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

详解Mysql的快照读和当前读区别

        在 MySQL InnoDB 中,读取数据的方式主要分为快照读(Snapshot Read)当前读(Current Read)两种,它们在并发控制、隔离级别实现中扮演着不同角色。     

1. 基本概念对比   

特性快照读 (Snapshot Read)当前读 (Current Read)
定义读取数据的历史版本读取数据的最新提交版本
实现基于 MVCC 机制基于锁机制
SQL 类型普通 SELECT 语句SELECT...FOR UPDATE, SELECT...LOCK IN SHARE MODE, INSERT, UPDATE, DELETE
隔离级别READ COMMITTED 和 REPEATABLE READ 下生效所有隔离级别
并发性读写不冲突读写可能冲突

2. 快照读详解 

2.1 工作机制

  • 通过 ReadView 访问 undo log 中的合适版本

  • 不需要加锁,读取的是某个时间点的数据快照

  • 受事务隔离级别影响:

    • READ COMMITTED:每次读取都生成新 ReadView

    • REPEATABLE READ:第一次读取时生成 ReadView

2.2 示例

-- 普通SELECT语句就是快照读
SELECT * FROM accounts WHERE id = 1;

2.3 特点

  • 无锁读取,性能高

  • 读取的数据可能不是最新的

  • 解决读写冲突,实现非阻塞读

3. 当前读详解

3.1 工作机制

  • 读取记录的最新提交版本

  • 会对记录加锁,防止其他事务修改

  • 保证读取的数据是最新的

3.2 当前读的SQL类型

-- 1. 加排他锁(X锁)的查询
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;-- 2. 加共享锁(S锁)的查询
SELECT * FROM accounts WHERE id = 1 LOCK IN SHARE MODE;-- 3. 数据修改操作(隐式当前读)
UPDATE accounts SET balance = 100 WHERE id = 1;
DELETE FROM accounts WHERE id = 1;
INSERT INTO accounts VALUES (...);

3.3 特点

  • 需要加锁,可能阻塞其他操作

  • 读取最新数据,保证数据一致性

  • 解决写写冲突

4. 核心区别

4.1 数据版本

  • 快照读:读取历史版本(通过undo log)

  • 当前读:读取最新提交版本

4.2 并发控制

  • 快照读:通过MVCC实现无锁并发

  • 当前读:通过锁机制实现并发控制

4.3 使用场景

  • 快照读:适用于普通查询,不要求数据绝对最新

  • 当前读:适用于需要保证数据一致性的场景,如账户交易

5.实际应用示例

场景:银行账户余额查询与转账

-- 事务1:查询余额(快照读)
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1; -- 快照读,返回1000-- 事务2:转账(当前读)
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE; -- 当前读,加X锁
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;-- 事务1再次查询
SELECT balance FROM accounts WHERE id = 1; -- 快照读,仍返回1000(REPEATABLE READ)
COMMIT;

6. 常见问题

Q:为什么UPDATE操作要先当前读?
A:因为UPDATE需要基于最新数据进行修改,必须先获取最新值并加锁防止其他事务同时修改。

Q:快照读是否完全不加锁?
A:在特殊情况下(如查询遇到正在被更新的数据),快照读可能需要等待锁释放,但这是例外情况。

Q:如何强制使用当前读?
A:在普通SELECT语句中添加FOR UPDATE或LOCK IN SHARE MODE后缀。

http://www.xdnf.cn/news/609283.html

相关文章:

  • 基于BERT预训练模型(bert_base_chinese)训练中文文本分类任务(AI老师协助编程)
  • 25年上半年五月之软考之设计模式
  • Linux基本指令(二)
  • 【Linux】基础开发工具(下)
  • Android正则表达式
  • Android中ServiceManager与Binder驱动的关系
  • java 进阶 1.0.3
  • 使用 Elasticsearch 和 Red Hat OpenShift AI 提升工作流程效率
  • C#日期和时间:DateTime转字符串全面指南
  • leetcode513.找树左下角的值:递归深度优先搜索中的最左节点追踪之道
  • Typescript学习教程,从入门到精通,TypeScript 集合类型语法知识点及案例代码(11)
  • 前缀和数组一文详解
  • Vue3.5 企业级管理系统实战(二十):角色菜单
  • JDK21全景图:关键特性与升级价值
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月23日第86弹
  • 如何轻松擦U盘? (3个解决方案)
  • AI Study,学习计划
  • 2024 CKA模拟系统制作 | Step-By-Step | 3、CKA考试系统的技术设置
  • 基于SpringBoot的网上租赁系统设计与实现
  • YOLOv10 系列算法学习笔记一
  • vue开发中常用方法笔记
  • springboot3+vue3融合项目实战-大事件文章管理系统-登录优化redis
  • Vue3和React中插件化设计思想
  • YOLO11解决方案之速度估算探索
  • LaTeX中所有数字都应该在数学环境中吗?
  • Python项目中的文件夹命名和结构设计建议
  • JavaScript的三大核心组成:ECMAScript、DOM与BOM
  • WebGL开发技巧
  • 一些Dify聊天系统组件流程图架构图
  • Idea如果有参数,怎么debug