Skip to content

Commit feca67f

Browse files
committed
[docs update]图片转存
1 parent 37e7a76 commit feca67f

16 files changed

+26
-27
lines changed
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

docs/database/mysql/innodb-implementation-of-mvcc.md

+21-21
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private:
7474

7575
**事务可见性示意图**[图源](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)):
7676

77-
![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)
77+
![trans_visible](./images/mvvc/trans_visible.png)
7878

7979
### undo-log
8080

@@ -89,27 +89,27 @@ private:
8989

9090
**`insert` 时的数据初始状态:**
9191

92-
![](https://ddmcc-1255635056.file.myqcloud.com/317e91e1-1ee1-42ad-9412-9098d5c6a9ad.png)
92+
![](./images/mvvc/317e91e1-1ee1-42ad-9412-9098d5c6a9ad.png)
9393

9494
2. **`update undo log`**`update``delete` 操作中产生的 `undo log`。该 `undo log`可能需要提供 `MVCC` 机制,因此不能在事务提交时就进行删除。提交时放入 `undo log` 链表,等待 `purge线程` 进行最后的删除
9595

9696
**数据第一次被修改时:**
9797

98-
![](https://ddmcc-1255635056.file.myqcloud.com/c52ff79f-10e6-46cb-b5d4-3c9cbcc1934a.png)
98+
![](./images/mvvc/c52ff79f-10e6-46cb-b5d4-3c9cbcc1934a.png)
9999

100100
**数据第二次被修改时:**
101101

102-
![](https://ddmcc-1255635056.file.myqcloud.com/6a276e7a-b0da-4c7b-bdf7-c0c7b7b3b31c.png)
102+
![](./images/mvvc/6a276e7a-b0da-4c7b-bdf7-c0c7b7b3b31c.png)
103103

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

106106
### 数据可见性算法
107107

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

110-
[具体的比较算法](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)
110+
[具体的比较算法](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)):
111111

112-
![](https://ddmcc-1255635056.file.myqcloud.com/8778836b-34a8-480b-b8c7-654fe207a8c2.png)
112+
![](./images/mvvc/8778836b-34a8-480b-b8c7-654fe207a8c2.png)
113113

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

@@ -138,45 +138,45 @@ private:
138138

139139
举个例子:
140140

141-
![](https://ddmcc-1255635056.file.myqcloud.com/6fb2b9a1-5f14-4dec-a797-e4cf388ed413.png)
141+
![](./images/mvvc/6fb2b9a1-5f14-4dec-a797-e4cf388ed413.png)
142142

143143
### 在 RC 下 ReadView 生成情况
144144

145-
1. **`假设时间线来到 T4 ,那么此时数据行 id = 1 的版本链为`**
145+
**1. 假设时间线来到 T4 ,那么此时数据行 id = 1 的版本链为:**
146146

147-
![](https://ddmcc-1255635056.file.myqcloud.com/a3fd1ec6-8f37-42fa-b090-7446d488fd04.png)
147+
![](./images/mvvc/a3fd1ec6-8f37-42fa-b090-7446d488fd04.png)
148148

149149
由于 RC 级别下每次查询都会生成`Read View` ,并且事务 101、102 并未提交,此时 `103` 事务生成的 `Read View` 中活跃的事务 **`m_ids` 为:[101,102]**`m_low_limit_id`为:104,`m_up_limit_id`为:101,`m_creator_trx_id` 为:103
150150

151151
- 此时最新记录的 `DB_TRX_ID` 为 101,m_up_limit_id <= 101 < m_low_limit_id,所以要在 `m_ids` 列表中查找,发现 `DB_TRX_ID` 存在列表中,那么这个记录不可见
152152
- 根据 `DB_ROLL_PTR` 找到 `undo log` 中的上一版本记录,上一条记录的 `DB_TRX_ID` 还是 101,不可见
153153
- 继续找上一条 `DB_TRX_ID`为 1,满足 1 < m_up_limit_id,可见,所以事务 103 查询到数据为 `name = 菜花`
154154

155-
2. **`时间线来到 T6 ,数据的版本链为`**
155+
**2. 时间线来到 T6 ,数据的版本链为:**
156156

157-
![markdown](https://ddmcc-1255635056.file.myqcloud.com/528559e9-dae8-4d14-b78d-a5b657c88391.png)
157+
![](./images/mvvc/528559e9-dae8-4d14-b78d-a5b657c88391.png)
158158

159159
因为在 RC 级别下,重新生成 `Read View`,这时事务 101 已经提交,102 并未提交,所以此时 `Read View` 中活跃的事务 **`m_ids`[102]**`m_low_limit_id`为:104,`m_up_limit_id`为:102,`m_creator_trx_id`为:103
160160

161161
- 此时最新记录的 `DB_TRX_ID` 为 102,m_up_limit_id <= 102 < m_low_limit_id,所以要在 `m_ids` 列表中查找,发现 `DB_TRX_ID` 存在列表中,那么这个记录不可见
162162

163163
- 根据 `DB_ROLL_PTR` 找到 `undo log` 中的上一版本记录,上一条记录的 `DB_TRX_ID` 为 101,满足 101 < m_up_limit_id,记录可见,所以在 `T6` 时间点查询到数据为 `name = 李四`,与时间 T4 查询到的结果不一致,不可重复读!
164164

165-
3. **`时间线来到 T9 ,数据的版本链为`**
165+
**3. 时间线来到 T9 ,数据的版本链为:**
166166

167-
![markdown](https://ddmcc-1255635056.file.myqcloud.com/6f82703c-36a1-4458-90fe-d7f4edbac71a.png)
167+
![](./images/mvvc/6f82703c-36a1-4458-90fe-d7f4edbac71a.png)
168168

169169
重新生成 `Read View`, 这时事务 101 和 102 都已经提交,所以 **m_ids** 为空,则 m_up_limit_id = m_low_limit_id = 104,最新版本事务 ID 为 102,满足 102 < m_low_limit_id,可见,查询结果为 `name = 赵六`
170170

171171
> **总结:** **在 RC 隔离级别下,事务在每次查询开始时都会生成并设置新的 Read View,所以导致不可重复读**
172172
173173
### 在 RR 下 ReadView 生成情况
174174

175-
**在可重复读级别下,只会在事务开始后第一次读取数据时生成一个 Read View(m_ids 列表)**
175+
在可重复读级别下,只会在事务开始后第一次读取数据时生成一个 Read View(m_ids 列表)
176176

177-
1. **`在 T4 情况下的版本链为`**
177+
**1. 在 T4 情况下的版本链为:**
178178

179-
![markdown](https://ddmcc-1255635056.file.myqcloud.com/0e906b95-c916-4f30-beda-9cb3e49746bf.png)
179+
![](./images/mvvc/0e906b95-c916-4f30-beda-9cb3e49746bf.png)
180180

181181
在当前执行 `select` 语句时生成一个 `Read View`,此时 **`m_ids`[101,102]**`m_low_limit_id`为:104,`m_up_limit_id`为:101,`m_creator_trx_id` 为:103
182182

@@ -186,11 +186,11 @@ private:
186186
- 根据 `DB_ROLL_PTR` 找到 `undo log` 中的上一版本记录,上一条记录的 `DB_TRX_ID` 还是 101,不可见
187187
- 继续找上一条 `DB_TRX_ID`为 1,满足 1 < m_up_limit_id,可见,所以事务 103 查询到数据为 `name = 菜花`
188188

189-
2. **`时间点 T6 情况下`**
189+
**2. 时间点 T6 情况下:**
190190

191-
![markdown](https://ddmcc-1255635056.file.myqcloud.com/79ed6142-7664-4e0b-9023-cf546586aa39.png)
191+
![](./images/mvvc/79ed6142-7664-4e0b-9023-cf546586aa39.png)
192192

193-
在 RR 级别下只会生成一次`Read View`,所以此时依然沿用 **`m_ids`[101,102]**`m_low_limit_id`为:104,`m_up_limit_id`为:101,`m_creator_trx_id` 为:103
193+
在 RR 级别下只会生成一次`Read View`,所以此时依然沿用 **`m_ids`[101,102]**`m_low_limit_id`为:104,`m_up_limit_id`为:101,`m_creator_trx_id` 为:103
194194

195195
- 最新记录的 `DB_TRX_ID` 为 102,m_up_limit_id <= 102 < m_low_limit_id,所以要在 `m_ids` 列表中查找,发现 `DB_TRX_ID` 存在列表中,那么这个记录不可见
196196

@@ -200,9 +200,9 @@ private:
200200

201201
- 继续找上一条 `DB_TRX_ID`为 1,满足 1 < m_up_limit_id,可见,所以事务 103 查询到数据为 `name = 菜花`
202202

203-
3. **时间点 T9 情况下:**
203+
**3. 时间点 T9 情况下:**
204204

205-
![markdown](https://ddmcc-1255635056.file.myqcloud.com/cbbedbc5-0e3c-4711-aafd-7f3d68a4ed4e.png)
205+
![](./images/mvvc/cbbedbc5-0e3c-4711-aafd-7f3d68a4ed4e.png)
206206

207207
此时情况跟 T6 完全一样,由于已经生成了 `Read View`,此时依然沿用 **`m_ids`[101,102]** ,所以查询结果依然是 `name = 菜花`
208208

docs/database/mysql/mysql-index.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tag:
1111

1212
**索引是一种用于快速查询和检索数据的数据结构。常见的索引结构有: B 树, B+树和 Hash。**
1313

14-
索引的作用就相当于目录的作用。打个比方: 我们在查字典的时候,如果没有目录,那我们就只能一页一页的去找我们需要查的那个字,速度很慢。如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。
14+
索引的作用就相当于书的目录。打个比方: 我们在查字典的时候,如果没有目录,那我们就只能一页一页的去找我们需要查的那个字,速度很慢。如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。
1515

1616
## 索引的优缺点
1717

@@ -179,8 +179,7 @@ SELECT id FROM table WHERE id=1;
179179

180180
如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。我们知道在 InnoDB 存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!
181181

182-
**覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,
183-
而无需回表查询。**
182+
**覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,而无需回表查询。**
184183

185184
> 如主键索引,如果一条 SQL 需要查询主键,那么正好根据主键索引就可以查到主键。
186185
>

docs/database/mysql/mysql-questions-01.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -317,15 +317,15 @@ mysql> SELECT @@tx_isolation;
317317
+-----------------+
318318
```
319319
320-
关于 MySQL 事务的详细介绍,可以看看我写的这篇文章:[MySQL 事务隔离级别详解](https://javaguide.cn/database/mysql/transaction-isolation-level.html)。
320+
关于 MySQL 事务隔离级别的详细介绍,可以看看我写的这篇文章:[MySQL 事务隔离级别详解](https://javaguide.cn/database/mysql/transaction-isolation-level.html)。
321321
322322
## MySQL 锁
323323
324324
### 表级锁和行级锁了解吗?有什么区别?
325325
326326
MyISAM 仅仅支持表级锁(table-level locking),一锁就锁整张表,这在并发写的情况下性非常差。
327327
328-
InnoDB 不光支持表级锁(table-level locking),还支持行级锁(row-level locking),默认为行级锁。行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说 InnoDB 的性能更高。
328+
InnoDB 不光支持表级锁(table-level locking),还支持行级锁(row-level locking),默认为行级锁。行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说 InnoDB 的性能更高。
329329
330330
**表级锁和行级锁对比**
331331

docs/java/basis/serialization.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ protostuff 基于 Google protobuf,但是提供了更多的功能和更简易
174174

175175
Github 地址:[https://github.com/protostuff/protostuff](https://github.com/protostuff/protostuff)
176176

177-
### hession
177+
### hessian
178178

179179
hessian 是一个轻量级的,自定义描述的二进制 RPC 协议。hessian 是一个比较老的序列化实现了,并且同样也是跨语言的。
180180

0 commit comments

Comments
 (0)