doc: 阅读mysql mvcc文档
This commit is contained in:
@@ -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可见
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user