衔接上篇,本篇来讲讲 修改过程中的
redo log,以及
LSN
前面讲 MTR 我们只提到 insert 对底层页面产生的原子操作。如果在执行过程中对记录发生了修改,有意思的事情就发生了:
- 不管怎么,页面都是刷到内存中操作;
- 存在内存 -> buffer pool【这块之前也说过】
- 直接改 bufferpool 中的页记录
- 改完这就是脏页了,加入 buffer pool 的
instance的flu_list
就来说说 flu_list和 LSN 的联系。
-
修改完缓存页,将页面对应的控制块插入
flu_list -
写入
oldest_modification,newest_modificationo_m:第一次被修改时,对应的MTR开始时对应的LSN赋值给这个变量n_m:每一次修改变量,对应的LSN都会被写入到这
所以这里也暗示:不管被修改多少次,
flu_list只会有第一次修改的控制块,此后都是不断修改n_m -
插入控制块的顺序是头插法。所以越靠近末尾的
LSN越小,越先被刷入磁盘。
Checkpoint
checkpoint 的设计就是为了在循环写入 ib_logfile0-N 过程中,标记哪些 redo log 以及是无用的【无用是指数据页已经刷盘了,真正持久化了,redo log 此时也就不需要再做什么宕机恢复啥的。】
这个时候引入:checkpoint_lsn,代表当前系统中可以被覆盖的 redo 日志总量是多少。
来看看一次 checkpoint 的流程:
首先
redo log如果被覆盖,说明脏页以及被刷盘。而脏页和LSN联系的地方是:
flu_list上的o_m, n_m
-
首先如果脏页已经刷盘,
flu_list中一定是没有这个控制块了,那么flu_list中最小的控制块【最后面的LSN最小】是目前最新要刷盘的页。把目前最小的控制块的
o_m赋值给checkpoint_lsn。 -
将
checkpoint_lsn和对应的redo log的全局日志偏移量以及目前为止做了多少次checkpoint这个次数,写入日志文件的管理信息中。
总结
总结一下 redo log 的特点和流程:
「特点」
- redo log 尽可能少,不然产生速度过快,脏页刷盘和log落盘都是很影响吞吐和性能的
- 因为不知道哪些 redo log 已经落盘,redo log 必须是可重入的,也就是 幂等性
- 为了可以加速重放,一个 redo log 只涉及到一个 page 的改动。所以实际存储的log file中存储的是修改的逻辑日志:
<page id, record offset, [update field(f1, v1)...]> - redo log 分类:
page redo log, space redo log, extra logic redo log
「组织」
sn每次增加一个mtr的log,这个值就是加上当前的log量。【指向当前写入的最后量】lsn这个值会加上blockheader & blocktrailer,每496b为一个单位划分【逻辑增长,这个不会被物理上的log循环给截断】ib_logfile这个默认是2,所以是物理循环的。lsn每增长两个就会换到下一个文件继续写。
未完待续。。。