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

mysql的mvcc

一、什么是MVCC

MySQL 的 MVCC(Multi-Version Concurrency Control,多版本并发控制) 是 InnoDB 存储引擎实现高并发事务的核心机制之一。它通过为每行数据维护多个版本,避免读写冲突,实现“读不阻塞写,写不阻塞读”,从而提高数据库的并发性能。

二、MVCC是如何实现的

MVCC 在 InnoDB 里的实现 = 隐藏字段(行级元数据) + Undo Log(存储旧版本) + Read View(快照判定) + Purge(垃圾回收)

1.当前读和快照读

快照读:即读取数据是从快照中获取的,事务在进行事务读取时不上锁,这就是mysql并发读写性能高的原因之一。 而当前读反之,读取数据时会上锁,这也就意味着即使你的隔离级别是可重复读,你用当前读也能读取到其他事务的最新结果,造成不可重复读。(mysql5.1之后的版本)

当前读:

  • 读取的是最新提交的数据,并且会加锁(共享锁或排他锁)。(mysql5.1之前InnoDB的默认方式)
  • 常见的当前读操作包括:
    • SELECT ... FOR UPDATE(加排他锁)
    • SELECT ... LOCK IN SHARE MODE(加共享锁)
    • UPDATEDELETEINSERT等操作

2. undo.log概念扫盲(撤销日志)

undo.log 用于记录数据修改前的状态,以便在事务回滚或需要读取历史版本时恢复数据。

每条记录修改前,系统会将旧值写入 undo.log,形成一条版本链。

3.readView(读视图)

readview 定义了事务在某一时刻对数据库的可见性视图,决定哪些数据版本对当前事务可见。

  • 已提交事务:已提交事务中记录的则是已经被提交的事务id集合。
  • 活跃事务:这个则记录那些还能活动且还没被提交的事务,其中min_trx_id指向活跃事务的最小值。
  • 未开始事务:这里面则是存放待使用的事务id值,其中max_trx_id就是记录这一块的最小值。
  • creator_trx_id:创建该 readview 的事务ID

4.可重复读(Repeatable Read)与读已提交(Read Committed)的区别

可重复读(Repeatable Read)--事务开始时快照
  • 在同一事务中多次读取同一数据时,保证结果一致,即使其他事务修改了该数据并提交。
  • 通过多版本并发控制(MVCC)实现,事务开始时创建一个快照,后续读取基于该快照。
  • 可能遇到幻读(Phantom Read)问题,即其他事务插入新数据并提交后,当前事务再次查询可能看到新数据。
读已提交(Read Committed)---每次查询时最新快照
  • 在同一事务中多次读取同一数据时,每次读取都能看到其他事务已提交的最新修改。
  • 仅保证不会读取到未提交的数据,但无法保证多次读取结果一致。
  • 通过MVCC或行级锁实现,每次查询时获取最新的已提交数据版本。
  • 可能遇到不可重复读(Non-repeatable Read)问题,即其他事务修改数据并提交后,当前事务再次查询可能看到不同结果。

关键差异

  • 一致性保证:可重复读保证同一事务内读取一致性;读已提交仅保证单次读取的已提交数据。
  • 隔离级别问题:可重复读可能幻读;读已提交可能不可重复读。
  • 实现方式:两者均可用MVCC实现,但快照生成策略不同(可重复读使用事务开始时快照,读已提交使用每次查询时最新快照)。

适用场景

  • 可重复读:需要事务内数据一致的场景,如财务报表生成。
  • 读已提交:对实时性要求高、允许数据变动的场景,如大多数OLTP系统。

示例数据库行为:

  • 事务A查询某行数据,事务B修改该行并提交。
    • 读已提交:事务A再次查询会看到B的修改。
    • 可重复读:事务A仍看到原始数据。

5. Purge 线程 = 垃圾回收

旧版本不能无限堆积。InnoDB 的 Purge 后台线程定期扫描 Undo Segment,
当确定某条旧记录 已无任何 Read View 需要 时,就会把它物理删除,释放页空间

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

相关文章:

  • 如何用Redis作为消息队列
  • Science Robotics 通过人机交互强化学习进行精确而灵巧的机器人操作
  • Flink框架:算子链的介绍
  • iview admin 使用mock.js模拟数据
  • 01_Python的in运算符判断列表等是否包含特定元素
  • C语言初学者笔记【动态内存管理】
  • 深入探讨集成学习:Bagging与Boosting的核心原理与实践
  • 自然语言处理——05 Transformer架构和手写实现
  • 复杂街景误检率↓79%!陌讯动态融合算法在街道垃圾识别的边缘计算优化​​
  • Mysql之binlog日志说明及利用binlog日志恢复数据操作记录
  • 链表漫游指南:C++ 指针操作的艺术与实践
  • 蓝牙链路层状态机精解:从待机到连接的状态跃迁与功耗控制
  • 【大语言模型 15】因果掩码与注意力掩码实现:深度学习中的信息流控制艺术
  • Python本源诗话(我DeepSeek)
  • 企业视频库管理高效策略
  • 大数据接口 - 企业风险报告(专业版)API接口文档
  • 使用springboot开发-AI智能体平台管理系统,统一管理各个平台的智能体并让智能体和AI语音设备通信,做一个属于自己的小艾同学~
  • 百度深度学习面试:batch_size的选择问题
  • 36_基于深度学习的智能零售柜物品检测识别系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)
  • 【深度学习新浪潮】有哪些工具可以帮助我们对视频进行内容分析和关键信息提取?
  • LeetCode56合并区间
  • Idea中 lombok 在“测试类中-单元测试”运行失败及解决方法
  • 商超高峰客流统计误差↓75%!陌讯多模态融合算法在智慧零售的实战解析
  • Elasticsearch:什么是神经网络?
  • Elasticsearch Persistence(elasticsearch-persistence)仓储模式实战
  • 批量归一化:不将参数上传到中心服务器,那服务器怎么进行聚合?
  • 浏览器解析网址的过程
  • 倍福下的EC-A10020-P2-24电机调试说明
  • 【JVM】JVM的内存结构是怎样的?
  • mysql为什么使用b+树不使用红黑树