doc: 阅读mysql undo文档
This commit is contained in:
@@ -480,7 +480,25 @@ trx_undo_t关联的则是上面描述的undo segment。
|
|||||||
#### undo writing
|
#### undo writing
|
||||||
当一个写事务开启时,将会通过`trx_assign_rseg_durable`分配Rollback Segment,内存中的trx_t也会指向对应的trx_rseg_t内存结构。
|
当一个写事务开启时,将会通过`trx_assign_rseg_durable`分配Rollback Segment,内存中的trx_t也会指向对应的trx_rseg_t内存结构。
|
||||||
|
|
||||||
rollback segment的分配策略很简单,会依次尝试下一个活跃的rollback segment。在此之后,如果事务内的第一条修改命令需要写undo record,将会调用`trx_undo_assign_undo`来获取undo segment。在获取undo segment时,`trx_rseg_t`中包含的cached list中节点将会被优先使用。sa
|
rollback segment的分配策略很简单,会依次尝试下一个活跃的rollback segment。在此之后,如果事务内的第一条修改命令需要写undo record,将会调用`trx_undo_assign_undo`来获取undo segment。在获取undo segment时,`trx_rseg_t`中包含的cached list中节点将会被优先使用。
|
||||||
|
> 如果已经存在`已分配但是未被使用的undo segment`,将会优先使用这部分undo segment。
|
||||||
|
>
|
||||||
|
> 如果不存在已分配但是未被使用的undo segment,将会调用trx_undo_create创建新的undo segment。
|
||||||
|
|
||||||
|
##### undo record写入
|
||||||
|
当undo page被写满后,会调用`trx_undo_add_page`来向当前undo segment中添加新的undo page。在将undo record写入到undo page时,存在如下约束:
|
||||||
|
- 一条undo record无法跨页面存在于两个page,如果当前page剩下的空间不足以写入undo record,那么会将undo record写入到下一个undo page
|
||||||
|
|
||||||
|
在事务完成之后(提交/回滚),
|
||||||
|
- `如果当前undo segment中只使用了一个undo page,并且undo page的使用率小于75%`,那么该undo segment将会被保留并添加到对应的insert/update cachedlist中
|
||||||
|
- `如果undo segment中undo page大于一个,或者undo page的使用率大于75%`,如么对于undo segment的处理如下:
|
||||||
|
- 对于insert类型的undo segment,其会在事务提交/回滚时直接被回收
|
||||||
|
- 对于update类型的undo segment,其会在purge完成后被回收
|
||||||
|
|
||||||
|
根据场景的不同,undo segment其header的状态将会从`TRX_UNDO_ACTIVE`变为`TRX_UNDO_FREE`/`TRX_UNDO_TO_PURGE`/`TRX_UNDO_CACHED`,其代表了innodb事务的结束。
|
||||||
|
|
||||||
|
#### undo for rollback
|
||||||
|
在回滚时,会按照undo record生成的时序,逆向进行回滚。回滚根据undo record的内容。
|
||||||
|
|
||||||
### purge
|
### purge
|
||||||
表`t`中,`a`为聚簇索引,`b`为辅助索引,若执行如下sql
|
表`t`中,`a`为聚簇索引,`b`为辅助索引,若执行如下sql
|
||||||
@@ -488,6 +506,18 @@ rollback segment的分配策略很简单,会依次尝试下一个活跃的roll
|
|||||||
delete from t where a=1;
|
delete from t where a=1;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
上图示例中,undo segment中包含了2个page和3个undo record:
|
||||||
|
- 第一个undo page中包含了undo record 1
|
||||||
|
- 第二个undo page中包含了undo record 2和undo record 3
|
||||||
|
|
||||||
|
回滚流程如下所示:
|
||||||
|
- 从undo segment header中获取last undo page header的位置
|
||||||
|
- 从last undo page header中获取最后一条undo record的位置,即undo record 3的位置,并根据undo record 3的内容执行回滚操作
|
||||||
|
- 根据prev record offset的值来获取上一条undo record的位置,如此逆向遍历undo page中所有的undo record,并且执行回滚操作
|
||||||
|
- 在当前page中,如果所有的undo records都执行完回滚操作,会根据undo page header查询前一个undo page,并按照上述流程执行回滚操作
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
上述语句造成的修改如下:
|
上述语句造成的修改如下:
|
||||||
- 将主键`a`为1的记录标记为delete,将记录`delete flag`设置为1(聚簇索引中的数据并没有被实际物理删除),`且会生成针对聚簇索引的undo log`。当事务发生回滚时,仅需将`delete flag`重新设置为0即可完成对删除的回滚。
|
- 将主键`a`为1的记录标记为delete,将记录`delete flag`设置为1(聚簇索引中的数据并没有被实际物理删除),`且会生成针对聚簇索引的undo log`。当事务发生回滚时,仅需将`delete flag`重新设置为0即可完成对删除的回滚。
|
||||||
- 对于辅助索引中满足`a=1`的记录,同样不会做任何处理,`也不会产生针对辅助索引的undo log`
|
- 对于辅助索引中满足`a=1`的记录,同样不会做任何处理,`也不会产生针对辅助索引的undo log`
|
||||||
|
|||||||
Reference in New Issue
Block a user