Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 46146f8

Browse files
[fix]数据可见性算法笔误&内容完善
1 parent 1fdb7f1 commit 46146f8

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

‎docs/database/mysql/InnoDB对MVCC的实现.md‎

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@
5656

5757
### ReadView
5858

59+
```c
60+
class ReadView {
61+
/* ... */
62+
private:
63+
trx_id_t m_low_limit_id; /* 大于这个 ID 的事务均不可见 */
64+
65+
trx_id_t m_up_limit_id; /* 小于这个 ID 的事务均可见 */
66+
67+
trx_id_t m_creator_trx_id; /* 创建该 Read View 的事务ID */
68+
69+
trx_id_t m_low_limit_no; /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */
70+
71+
ids_t m_ids; /* 创建 Read View 时的活跃事务列表 */
72+
73+
m_closed; /* 标记 Read View 是否 close */
74+
}
75+
```
76+
5977
[`Read View`](https://github.com/facebook/mysql-8.0/blob/8.0/storage/innobase/include/read0types.h#L298) 主要是用来做可见性判断,里面保存了 "当前对本事务不可见的其他活跃事务"
6078

6179
主要有以下字段:
@@ -65,6 +83,10 @@
6583
- `m_ids`:`Read View` 创建时其他未提交的活跃事务 ID 列表。创建 `Read View`时,将当前未提交事务 ID 记录下来,后续即使它们修改了记录行的值,对于当前事务也是不可见的。`m_ids` 不包括当前事务自己和已提交的事务(正在内存中)
6684
- `m_creator_trx_id`:创建该 `Read View` 的事务 ID
6785

86+
**事务可见性示意图**([图源](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/#MVCC-1)):
87+
88+
![trans_visible](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/trans_visible.jpg)
89+
6890
### undo-log
6991

7092
`undo log` 主要有两个作用:
@@ -90,23 +112,23 @@
90112

91113
![](https://ddmcc-1255635056.file.myqcloud.com/6a276e7a-b0da-4c7b-bdf7-c0c7b7b3b31c.png)
92114

93-
不同事务或者相同事务的对同一记录行的修改,会使该记录行的 `undo log` 成为一条链表,链首就是最新的记录,链尾就是最早的旧记录
115+
不同事务或者相同事务的对同一记录行的修改,会使该记录行的 `undo log` 成为一条链表,链首就是最新的记录,链尾就是最早的旧记录
94116

95117
### 数据可见性算法
96118

97119
`InnoDB` 存储引擎中,创建一个新事务后,执行每个 `select` 语句前,都会创建一个快照(Read View),**快照中保存了当前数据库系统中正处于活跃(没有 commit)的事务的 ID 号**。其实简单的说保存的是系统中当前不应该被本事务看到的其他事务 ID 列表(即 m_ids)。当用户在这个事务中要读取某个记录行的时候,`InnoDB` 会将该记录行的 `DB_TRX_ID``Read View` 中的一些变量及当前事务 ID 进行比较,判断是否满足可见性条件
98120

99121
[具体的比较算法](https://github.com/facebook/mysql-8.0/blob/8.0/storage/innobase/include/read0types.h#L161)如下:[图源](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/#MVCC-1)
100122

101-
![markdown](https://ddmcc-1255635056.file.myqcloud.com/8778836b-34a8-480b-b8c7-654fe207a8c2.png)
123+
![](https://ddmcc-1255635056.file.myqcloud.com/8778836b-34a8-480b-b8c7-654fe207a8c2.png)
102124

103125
1. 如果记录 DB_TRX_ID < m_up_limit_id,那么表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照之前就提交了,所以该记录行的值对当前事务是可见的
104126

105127
2. 如果 DB_TRX_ID >= m_low_limit_id,那么表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照之后才修改该行,所以该记录行的值对当前事务不可见。跳到步骤 5
106128

107129
3. m_ids 为空,则表明在当前事务创建快照之前,修改该行的事务就已经提交了,所以该记录行的值对当前事务是可见的
108130

109-
4. 如果 m_up_limit_id <= DB_TRX_ID < m_up_limit_id,表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照的时候可能处于"活动状态"或者"已提交状态";所以就要对活跃事务列表 m_ids 进行查找(源码中是用的二分查找,因为是有序的)
131+
4. 如果 m_low_limit_id <= DB_TRX_ID < m_up_limit_id,表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照的时候可能处于"活动状态"或者"已提交状态";所以就要对活跃事务列表 m_ids 进行查找(源码中是用的二分查找,因为是有序的)
110132

111133
- 如果在活跃事务列表 m_ids 中能找到 DB_TRX_ID,表明:1 在当前事务创建快照前,该记录行的值被事务 ID 为 DB_TRX_ID 的事务修改了,但没有提交;或者 2 在当前事务创建快照后,该记录行的值被事务 ID 为 DB_TRX_ID 的事务修改了。这些情况下,这个记录行的值对当前事务都是不可见的。跳到步骤 5
112134

@@ -210,6 +232,6 @@
210232
## 参考
211233

212234
- **《MySQL 技术内幕 InnoDB 存储引擎第 2 版》**
213-
214235
- [Innodb 中的事务隔离级别和锁的关系](https://tech.meituan.com/2014/08/20/innodb-lock.html)
215236
- [MySQL 事务与 MVCC 如何实现的隔离级别](https://blog.csdn.net/qq_35190492/article/details/109044141)
237+
- [InnoDB 事务分析-MVCC](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /