doc: 阅读mysql undo log文档
This commit is contained in:
@@ -379,6 +379,44 @@ undo log中主要存储旧的col值,用于在回滚或mvcc时为undo操作提
|
||||
- `TRX_UNDO_DEL_MARK_REC`类型的记录,对应`将原记录标记为删除`的回滚
|
||||
- `TRX_UNDO_INSERT_REC`类型的记录,标记对`新纪录`的插入回滚
|
||||
|
||||
> 对于insert/update undo log record,每条undo record均只针对一条记录。故而,当一条sql语句对多行记录进行删除/更改时,会生成多条insert/update undo record。
|
||||
|
||||
### undo log组织形式
|
||||
上述内容介绍了undo log record的格式,为了对undo log records进行高效率的访问和管理,undo log record应当以适当的形式被组织。
|
||||
|
||||
#### undo log的逻辑组织方式
|
||||
每个事务都会修改一系列的records,并产生相应的undo log records,事务对应的undo log由这些undo log records组成。
|
||||
|
||||
undo log除了由undo log record组成外,其还包含了一个undo log header,结构如下:
|
||||
|
||||
<img src="https://yqintl.alicdn.com/4eeedc0d845c26417e570782cb01824f98d7dcd3.png" alt="3" title="3">
|
||||
|
||||
如上述结构所示,undo log header中包含如下部分:
|
||||
- trx id: 事务id,用于标识产生该undo log的事务
|
||||
- trx no: trx no用于表示事务的提交顺序(header中trx no并非一定有值,在事务提交前,该field未定义,当事务提交后,该field会被填充)
|
||||
- `trx no`用于判断`是否purge应当被执行`
|
||||
- delete mark: 判断是否undo log中存在`TRX_UNDO_DEL_MARK_REC`类型的undo record,从而在purge时避免扫描
|
||||
- log start offset: 该field记录了undo log header结尾的位置,便于后续对undo log header进行拓展
|
||||
- History List Node:undo log通过该结构挂载到History List中
|
||||
|
||||
> 故而,undo log就粒度存在两种结构
|
||||
> - undo record: 记录每行数据的历史版本,行数据通过维护undo record chain来还原历史版本
|
||||
> - undo log: 针对事务级别,每个undo log由undo log header和多个undo records组成,并且undo log会根据事务的提交顺序被挂载到history list中
|
||||
|
||||
##### record versions
|
||||
如果多个事务针对同一条record进行了修改(串行),那么,每个事务对record造成的修改都会生成不同的版本(version),不同的版本之间通过链表进行链接,用于后续的mvcc,示例如下:
|
||||
|
||||
<img src="https://yqintl.alicdn.com/ee4f6e18f7fb39e128e06d26daed3432ff203390.png" alt="4" title="4">
|
||||
|
||||
如上所示,事务`I, J, K`都对`id=1`的记录进行了操作,其操作顺序如下:
|
||||
1. 事务I插入了id为1的记录,并且将`a`的值设置为A
|
||||
2. 事务J将id为1记录的`a`修改为了B
|
||||
3. 事务K将id为1记录的`a`修改为了C
|
||||
|
||||
事务I, J, K都有其事务对应的undo log,并且每个undo log都拥有对应的undo log header和undo log records。
|
||||
|
||||
通过index中的记录及其rollptr引用的链表,可以对记录关联的`I, J, K`三个版本进行还原。
|
||||
|
||||
### purge
|
||||
表`t`中,`a`为聚簇索引,`b`为辅助索引,若执行如下sql
|
||||
```sql
|
||||
@@ -386,7 +424,7 @@ delete from t where a=1;
|
||||
```
|
||||
|
||||
上述语句造成的修改如下:
|
||||
- 将主键`a`为1的记录标记为delete,将记录`delete flag`设置为1(聚簇索引中的数据并没有被实际物理删除),`且会生成针对聚簇索引的undo log`
|
||||
- 将主键`a`为1的记录标记为delete,将记录`delete flag`设置为1(聚簇索引中的数据并没有被实际物理删除),`且会生成针对聚簇索引的undo log`。当事务发生回滚时,仅需将`delete flag`重新设置为0即可完成对删除的回滚。
|
||||
- 对于辅助索引中满足`a=1`的记录,同样不会做任何处理,`也不会产生针对辅助索引的undo log`
|
||||
|
||||
> undo log只针对聚簇索引生成,对于辅助索引的变化并不会生成对应的undo log。
|
||||
@@ -401,8 +439,3 @@ delete from t where a=1;
|
||||
|
||||
#### history
|
||||
innodb存储引擎中维护了一个history列表,其`根据事务的提交顺序`对undo log进行链接,`在history list中,先提交的事务其undo log位于history list的尾端`。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user