diff --git a/mysql/mysql文档/mysql_mvcc_impl.md b/mysql/mysql文档/mysql_mvcc_impl.md index f0ea0f6..9ce8dad 100644 --- a/mysql/mysql文档/mysql_mvcc_impl.md +++ b/mysql/mysql文档/mysql_mvcc_impl.md @@ -10,6 +10,13 @@ - [innodb\_purge\_threads](#innodb_purge_threads) - [innodb\_max\_purge\_lag](#innodb_max_purge_lag) - [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 @@ -92,3 +99,52 @@ purge操作在后台由一个或多个purge threads执行。purge threads的数 > 如果`当前辅助索引中的数据被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可见 +