当前位置: 首页 > 图灵资讯 > 技术篇> 浅谈MVCC

浅谈MVCC

来源:图灵教育
时间:2023-06-14 09:50:51

并发控制多版本(Multi-Version Concurrency Control, MVCC)

可视为行级锁的变种。在许多情况下,它避免了锁定操作,因此成本较低。不仅是 Mysql,包括 Oracle、PostgreSQL 其他数据库都实现了自己的目标 MVCC,实现机制没有统一的标准。MVCC 是 InnoDB 存储引擎实现隔离水平的具体方法是实现提交读取和重复读取的两个隔离水平。不提交阅读隔离级别总是阅读最新的数据线,要求很低,不需要使用 MVCC。串行隔离等级需要锁定所有读取的行,并简单使用 MVCC 无法实现。

浅谈MVCC_后端

MVCC和锁

锁可以解决多个事务同时执行时的并发一致性问题。在实际情况下,阅读操作往往大于写作操作,因此引入了阅读和写作锁,以避免不必要的锁操作。例如,阅读和阅读之间没有相互排斥的关系。阅读和写作锁中的阅读和写作操作仍然相互排斥。注: MYSQL MVCC只有RC和R级别。而且只有在快照阅读场景中讨论MVCC才有意义。

MVCC的思想

在某个时间点保存数据快照,并编写操作(DELETE、INSERT、UPDATE)更新最新版本的快照;然而,阅读操作以阅读旧版本的快照并不重要。这与此有关。 CopyOnWrite 类似。

版本号 InnoDB 的 MVCC 实现是:在每行记录后面保存两个隐藏列,一个列存储银行的创建时间,另一个列存储银行的过期时间(这里的时间是指系统版本号)。每次新事务开始时,系统版本号都会自动增加,系统版本号将作为事务的版本号,用于与每行记录的版本号进行比较。

系统版本号 SYS_ID:这是一个增加的数字,每次开始新的事务,系统版本号都会自动增加。

事务版本号 TRX_ID :系统版本号在事务开始时。

Undo 日志 MVCC 多版本是指存储在多个版本中的快照 Undo 在日志中,日志通过回滚指针 ROLL_PTR 连接一个数据行的所有快照。

例如在 MySQL 创建一个表 t,包含主键 id 和一个字段 x。我们先插入一个数据行,然后对数据行进行两次更新。

INSERT INTO t(id, x) VALUES(1, "a");UPDATE t SET x="b" WHERE id=1;UPDATE t SET x="c" WHERE id=1;

因为没用 START TRANSACTION 以上操作作为执行事务的事务

根据 MySQL 的 AUTOCOMMIT 机制,每一项操作都将作为一项事务来执行

因此,上述操作共涉及三个事务。除了记录事务版本号外,快照还记录了事务版本号 TRX_ID 除了操作,还记录了一个 bit 的 DEL 用于标记是否删除的字段。

浅谈MVCC_后端_02

INSERT、UPDATE、DELETE 操作将创建一个日志,并将事务版本号 TRX_ID 写入。DELETE 可以看作是一种特殊的东西 UPDATE,还会额外将 DEL 字段设置为 1。ReadView 读视图

Readview读视图

MVCC 维护一致性读视图 consistent read view ,主要包括当前系统未提交的事务列表 TRX_IDs {TRX_ID_1, TRX_ID_2, ...},还有列表的最小值 TRX_ID_MIN 和 TRX_ID_MAX。

浅谈MVCC_后端_03

这样,对于当前事务的启动时刻,数据版本 row trx_id,有以下可能性:如果它落在绿色部分,则表示该版本是由提交的事务或当前事务本身生成的,则该数据可见;如果它落在红色部分,则表示该版本是由未来启动的事务生成的,这当然是看不见的;如果它落在黄色部分,则包括两种情况

a. 若 row trx_id 在数组中,这个版本是由未提交的事务生成的,这是看不见的

b. 若 row trx_id 不在数组中,说明这个版本是已经提交的事务生成的,可见