doc: 阅读mysql mvcc文档

This commit is contained in:
asahi
2025-08-14 19:49:26 +08:00
parent dcafbb38d8
commit dee8180b4d

View File

@@ -10,6 +10,13 @@
- [innodb\_purge\_threads](#innodb_purge_threads) - [innodb\_purge\_threads](#innodb_purge_threads)
- [innodb\_max\_purge\_lag](#innodb_max_purge_lag) - [innodb\_max\_purge\_lag](#innodb_max_purge_lag)
- [Multi-Versioning and Secondary Indexes](#multi-versioning-and-secondary-indexes) - [Multi-Versioning and Secondary Indexes](#multi-versioning-and-secondary-indexes)
- [mvcc mechanism](#mvcc-mechanism)
- [read view](#read-view)
- [read view for read committed isolation level](#read-view-for-read-committed-isolation-level)
- [read view for repeatable read isolation level](#read-view-for-repeatable-read-isolation-level)
- [read view impl](#read-view-impl)
- [innodb clustered index hidden columns](#innodb-clustered-index-hidden-columns)
- [implementation principle](#implementation-principle)
# mysql mvcc # mysql mvcc
@@ -92,3 +99,52 @@ purge操作在后台由一个或多个purge threads执行。purge threads的数
> 如果`当前辅助索引中的数据被delete marked`或`当前辅助索引页被newer transaction所更新`,那么`covering index`技术将不会被使用。故而并不会直接从辅助索引中返回值innodb而是会再次从clustered index中查询记录。 > 如果`当前辅助索引中的数据被delete marked`或`当前辅助索引页被newer transaction所更新`,那么`covering index`技术将不会被使用。故而并不会直接从辅助索引中返回值innodb而是会再次从clustered index中查询记录。
## mvcc mechanism
mvcc机制主要用于处理多事务之间对数据的并发访问并且通过`版本快照`来实现事务之间的数据隔离。
事务A可见的数据版本为`事务A开启时的数据版本`即使在事务A执行的过程中事务B对数据进行了修改事务A后续读取时仍然读取的是修改之前的版本。
综上所属根据mvcc机制可以实现可重复读的隔离级别。
### read view
在mvcc中存在`read view`这一概念,其原理类似于如下描述:
- 在事务开启时,为所有数据创建一个快照,后续该事务在执行过程中都会从快照中读取数据,从而可以消除其他事务修改数据所造成的影响
#### read view for read committed isolation level
对于`read committed`隔离级别的事务,其等价于`generate a read view before each select statement is executed`
#### read view for repeatable read isolation level
对于`repeatable read`隔离级别的事务,其等价于`generate a read view before transaction executes the first select statement`并且在后续整个事务的执行过程中都使用该read view。
#### read view impl
read view实现并非是简单的为所有数据创建一个备份其原理如下。
read view在被创建时会记录如下信息
- `m_ids`当read view被创建时read view会记录当前数据库中所有活跃事务id的集合
- `min_trx_id` 该field代表当read view被创建时数据库中所有活跃事务id中的最小值相当于`m_ids`集合中的最小值
- `max_trx_id` 该值代表当`read view被创建时``数据库将要授予下一个新创建事务的事务id`,即`当前全局最大的事务id + 1`
- `creator_trx_id`代表创建该read view的事务id
#### innodb clustered index hidden columns
除了read view外innodb mvcc中还包含另外的部分`hidden_columns`
innodb的clustered index中会包含如下hidden columns
- `trx_id` 代表最后对该clustered index record进行修改的事务id
- `roll_pointer` 每当clustered index record被修改时指向`记录数据旧版本undo log`的指针会被写入到该column中。故而`roll_pointer`包含了一个单向链表,`包含clustered index record所有的旧版本`
#### implementation principle
通过上述记录的read view信息和clustered index hidden columns信息可以决定数据的历史版本对事务是否可见`每个历史版本中都包含trx_id信息用于代表该版本的最后修改事务id`
- `trx_id = creator_trx_id`: 如果`数据最后被修改的事务id``创建read view的事务id`相同,那么该行数据版本对当前事务可见
- `trx_id < min_trx_id`:如果`行数据的最后被修改事务id`小于`read view中最小的活跃事务id`代表read view创建时trx_id对应的事务已经被提交此时该行数据版本对当前事务可见
- `trx_id >= max_trx_id`:如果`行数据最后被修改的事务id`大于或等于`read view被创建时的全局最大事务id + 1`read view创建时`该数据版本对应的修改事务id还不存在`即read view创建时该修改还未发生故而该行数据版本对当前事务不可见
- `min_trx_id <= trx_id < max_trx_id`:
- `trx_id位于m_ids中`如果trx位于m_ids中代表read view在创建时该数据版本对应的事务还未提交即该数据版本对事务不可见
- `trx_id未位于m_ids中`: 代表在read view创建时该数据版本对应的事务已经提交故而该行数据版本可见
> read view通过记录创建时的`活跃事务id列表`和`全局最大事务id + 1`,可以明确的区分`数据版本的最后修改事务id造成的修改`是否对readview可见其判断逻辑如下
> - 对于id大于等于`全局最大事务id + 1`的事务在read view创建时都没有被创建故而未来事务造成的修改对read view不可见
> - 对于id小于`最小活跃事务id`的事务代表在read view创建时已提交read view创建之前提交的事务对read view是可见的
> - 对于id位于`[min_trx_id, max_trx_id)`之间的事务,其是否可见取决于其是否位于`活跃事务id列表`中来进行判断
> - 如果位于`活跃事务id列表`中代表read view创建时该历史版本对应修改还未提交故而对read view不可见
> - 如果不位于`活跃事务id列表`中代表read view创建时该历史版本对应修改已经提交已提交事务的修改对read view可见