文章目录
- 1 问题背景
- 2 前言
- 3 什么是MVCC
- 4 必备知识
- 4.1 行记录的三个隐藏字段
- 4.2 版本链
- 4.3 一致性读(快照读)和锁定读(当前读)
- 4.4 Read View
- 4.4.1 简介
- 4.4.2 ReadView类
- 5 实现原理
- 5.1 如何通过ReadView来判断记录的哪个版本是否可见
- 5.2 何时生成ReadView快照
- 6 总结
1 问题背景
生产环境上的电商项目中,常常遇到MySQL等待锁超时的报错,实际场景常见于批量更新店铺的税费(针对地区批量更新)、批量更新商品系列的内容等等 。因此来研究MySQL的MVCC知识 。
参考自2 前言
- MySQL官方文档——InnoDB Multi-Versioning
- MySQL专有名词文档——MySQL Glossary
- 【MySQL笔记】正确的理解MySQL的MVCC及实现原理
- 面试题60:请概述一下,什么是MVCC?那版本链呢?ReadView又有什么用?
- ReadView 类的官方文档介绍
3 什么是MVCC
- 本篇博客注重讲述实现原理,很多处地方可能晦涩难懂,读一次半次理解不了是很正常的 。需要反复阅读并思考,细细品味才能慢慢理解 。前两三次不必追求背诵它,先浏览并理解个大概,再反复细致阅读并思考 。
- 此博客的用意在于更好地理解工作中CRUD的底层原理,以及理解MySQL是如何处理并发请求的 。学习MVCC对自身价值也能有很大帮助(比如自身的知识体系广度以及深度,提高分析、定位生产问题的能力,面试等) 。
- 笔者学习MVCC的方式是以MySQL官方文档为主(避免学习了别人错误的理解),以别人的博客、微信相关为辅(他人写出来的文档思路非常值得学习) 。
- 本文如有不正确的地方或疑惑,请于评论处指正
官方原文:
InnoDB is a multi-version storage engine. It keeps information about old versions of changed rows to support transactional features such as concurrency and rollback. This information is stored in undo tablespaces in a data structure called a rollback segment. See Section 15.6.3.4, “Undo Tablespaces”. InnoDB uses the information in the rollback segment to perform the undo operations needed in a transaction rollback. It also uses the information to build earlier versions of a row for a consistent read. See Section 15.7.2.3, “Consistent Nonlocking Reads”.
MVCC,全称Multi-Version Concurrency Control,译为多版本并发控制 。InnoDB是一个多版本的存储引擎 。它会保存着被变更的记录的老版本信息,以此来支持事务的特性,比如并发、回滚 。这些信息以被称为回滚段的数据结构被存储在undo表空间(一个回滚段中有若干条undo log,若干条undo log会形成一个链表(常称为版本链),一个undo表空间中有若干个回滚段) 。详情看Section 15.6.3.4, “Undo Tablespaces” 。InnoDB使用回滚段中的信息来执行事务回滚过程中所需的回滚操作 。InnoDB也使用回滚段中的信息来构建一行记录的早期版本,以此来实现一致性读取 。详情见Section 15.7.2.3, “Consistent Nonlocking Reads” 。总结:
MVCC是InnoDB的一种机制,用于支持事务的某些特性,比如并发、回滚 。实际场景有回滚和一致性读取 。实现原理涉及到undo log 。记录的若干版本信息存储在回滚段中,即一个回滚段有若干条回滚段4 必备知识
学习以下这些必备知识,能更加容易理解MVCC的实现原理4.1 行记录的三个隐藏字段
-
DB_TRX_ID:6个字节,该字段表示插入或更新行记录时的最新事务标识 。一个delete操作被内部当成一个update操作来处理,行记录的一个特定的比特位会被标记,作为该行记录已被删除 。
-
DB_ROLL_PTR:7个字节,该字段称作回滚指针 。回滚指针指向回滚段中的一条undo log记录,其实就是指向记录的上一个版本 。如果行记录被更新,undo log记录会保存必要的信息来重构行记录被更新前的内容 。
-
DB_ROW_ID:6个字节,该字段称作行ID,当有新行被插入时,行ID会自增 。如果 InnoDB自动生成聚集索引,则索引包含行 ID 值 。否则,该 DB_ROW_ID列不会出现在任何索引中 。
MySQL官方文档并没有关于版本链的介绍,但理解这个概念相当重要 。此处仅简单介绍版本链是什么,后面会详细介绍其中的细节 。
假设现在有一张表t_sku,记录商品sku的售价、原价、库存、sku名称等等 。现在事务A往该表 插入一条记录,此时t_sku表的情况如下所示:
每次
insert、update操作后,该条记录被变更前的信息都会被放入回滚段中,被放入回滚段中的这条记录称为undo log 。因为是insert操作,事务提交后,该条undo就会立刻被销毁【1】
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
