聊聊Mysql的MVCC

1 什么是MVCC?

MVCC,是Multiversion Concurrency Control的缩写,翻译过来是多版本并发控制 ,和数据库锁一样,他也是一种并发控制的解决方案。
我们知道,在数据库中,对数据的操作主要有2种,分别是读和写,而在并发场景下,就可能出现以下三种情况:
读-读并发
读-写并发
写-写并发
我们都知道,在没有写的情况下读-读并发是不会出现问题的,而写-写并发这种情况比较常用的就是通过加锁的方式实现。那么,读-写并发则可以通过MVCC的机制解决。

快照读和当前读

在介绍MVCC前,我们先说一下什么是快照读和当前读

快照读

简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据, 不加锁,是非阻塞读。
不同的隔离级别,同一事物中的快照读不一样
• Read Committed:每次select,都生成一个快照读。
• Repeatable Read:开启事务后第一个select语句才是快照读的地方,之后的select读取的数据和第一次一样(和后面生成readview有关),看到后面的readview就理解了。
• Serializable:快照读会退化为当前读

当前读

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加 锁。对于我们日常的操作,如:select ... lock in share mode(共享锁),select ...
for update、update、insert、delete(排他锁)都是一种当前读。

隐藏字段

当我们创建了一张表,有自己创建的字段,实际上除了这自己创建的字段以外,InnoDB还会自动的给我们添加三个隐藏字段及其含义分别是:

而上述的前两个字段是肯定会添加的, 是否添加最后一个字段DB_ROW_ID,得看当前表有没有主键,如果有主键,则不会添加该隐藏字段。

undolog

回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即
被删除。
回滚日志就是一条条数据(版本)组成的版本链,每一次记录变更之前都会先存储一份快照到undo log中,那么这几个隐式字段也会跟着记录一起保存在undo log中,就这样,每一个快照中都有一个db trx id字段表示了对这个记录做了最新一次修改的事务的ID以及一个db roll ptr字段指向了上一个快照的地址。(db trx id和db roll ptr是重点,后面还会用到)

readview

ReadView(读视图)是快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务 (未提交的)id。
ReadView中包含了四个核心字段:


而在readview中就规定了版本链数据的访问规则:
trx_id 代表当前undolog版本链对应事务ID。

流程如下:

不同的隔离级别,生成ReadView的时机不同:
READ COMMITTED :在事务中每一次执行快照读时生成ReadView。
REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

相关推荐
2401_88445415几秒前
Python测试代码如何实现自解释_使用pytest描述性命名规范
jvm·数据库·python
敖正炀1 分钟前
InnoDB 引擎深度:B+Tree、页与行格式
mysql
.柒宇.3 分钟前
Redis哨兵模式搭建
数据库·redis·哨兵
敖正炀3 分钟前
事务与 MVCC:Undo Log、ReadView 与隔离级别
mysql
dinglu1030DL9 分钟前
Go语言怎么格式化时间_Go语言time.Format教程【详解】
jvm·数据库·python
老码观察11 分钟前
K8s集群断电后MySQL恢复实录:从InnoDB崩溃到数据完整迁移
mysql·adb·kubernetes
敖正炀12 分钟前
MySQL 架构全景与特性总览
mysql
环流_12 分钟前
Redis单线程但效率高且快
数据库·redis·缓存
m0_6245785913 分钟前
SQL数据分析如何剔除极端异常值_配合窗口函数检测偏离度
jvm·数据库·python
tkevinjd14 分钟前
MySQL1:分层架构
数据库·mysql·缓存