腾讯面试:MySQL事务与MVCC如何实现的隔离级别?( 三 )
MVCC 解决数据丢失MVCC , 多版本的并发控制 , Multi-Version Concurrency Control 。
使用版本来控制并发情况下的数据问题 , 在B事务开始修改账户且事务未提交时 , 当A事务需要读取账户余额时 , 此时会读取到B事务修改操作之前的账户余额的副本数据 , 但是如果A事务需要修改账户余额数据就必须要等待B事务提交事务 。
MVCC使得数据库读不会对数据加锁 , 普通的SELECT请求不会加锁 , 提高了数据库的并发处理能力 。借助MVCC , 数据库可以实现READ COMMITTED , REPEATABLE READ等隔离级别 , 用户可以查看当前数据的前一个或者前几个历史版本 , 保证了ACID中的I特性(隔离性) 。
InnoDB的MVCC实现逻辑InnoDB存储引擎保存的MVCC的数据InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现的 。 一个保存了行的事务ID(DB_TRX_ID) , 一个保存了行的回滚指针(DB_ROLL_PT) 。 每开始一个新的事务 , 都会自动递增产 生一个新的事务id 。 事务开始时刻的会把事务id放到当前事务影响的行事务id中 , 当查询时需要用当前事务id和每行记录的事务id进行比较 。
下面看一下在REPEATABLE READ隔离级别下 , MVCC具体是如何操作的 。
SELECT
InnoDB 会根据以下两个条件检查每行记录:
- InnoDB只查找版本早于当前事务版本的数据行(也就是 , 行的事务编号小于或等于当前事务的事务编号) , 这样可以确保事务读取的行 , 要么是在事务开始前已经存在的 , 要么是事务自身插入或者修改过的 。
- 删除的行要事务ID判断 , 读取到事务开始之前状态的版本 , 只有符合上述两个条件的记录 , 才能返回作为查询结果 。
InnoDB为新插入的每一行保存当前事务编号作为行版本号 。
DELETE
InnoDB为删除的每一行保存当前事务编号作为行删除标识 。
UPDATE
InnoDB为插入一行新记录 , 保存当前事务编号作为行版本号 , 同时保存当前事务编号到原来的行作为行删除标识 。
保存这两个额外事务编号 , 使大多数读操作都可以不用加锁 。 这样设计使得读数据操作很简单 , 性能很好 , 并且也能保证只会读取到符合标准的行 。 不足之处是每行记录都需要额外的存储空间 , 需要做更多的行检查工作 , 以及一些额外的维护工作 。
MVCC只在REPEATABLE READ和READ COMMITIED两个隔离级别下工作 。 其他两个隔离级别都和 MVCC不兼容, 因为READ UNCOMMITIED总是读取最新的数据行 , 而不是符合当前事务版本的数据行 。 而SERIALIZABLE则会对所有读取的行都加锁 。
MVCC 在mysql 中的实现依赖的是 undo log 与 read view。
undo log根据行为的不同 , undo log分为两种: insert undo log 和 update undo log
- insert undo log:
purge的主要任务是将数据库中已经 mark del 的数据删除 , 另外也会批量回收undo pages
数据库 Insert时的数据初始状态:
文章插图
- update undo log: update 或 delete 操作中产生的 undo log 。因为会对已经存在的记录产生影响 , 为了提供 MVCC机制 , 因此update undo log 不能在事务提交时就进行删除 , 而是将事务提交时放到入 history list 上 , 等待 purge 线程进行最后的删除操作 。数据第一次被修改时:
文章插图
- 华为、腾讯、万科员工职业发展体系建设与实践
- 阿里腾讯都在做的可视化大屏,我用这工具里的100个模板实现了
- 腾讯游戏开发工程师:Linux 机器 CPU 毛刺问题排查
- 一个普通本科的安卓程序员如何才能进腾讯,阿里,字节这些大厂?
- 阿里铁军原主帅俞朝翎:阿里面试中的“望闻问切”法
- 腾讯|蚂蚁员工人人喜提283平米大房子?你想多了
- 腾讯发出警告!这个流氓APP千万别装:秒变“紧箍咒”
- 内容|2020腾讯ConTech大会:基于信赖,30位嘉宾带用户打开眼界
- 腾讯关联企业入股VR游戏开发商,持股39%
- 中国音乐行业洗牌,昔日巨头曲终人散,网易云成腾讯唯一对手