最近在学习OceanBase事务相关的内容,关于Undo/Redo日志,和大家一起交流下。

Undo/Redo 日志

日志就是记录事务相关操作的文件,每个改变数据库的操作都会生成日志记录,在系统故障发生之后,我们可以通过日志将数据库恢复到一致性状态。

Undo 日志记录

回滚日志(Undo log),它通过撤销未提交的事务来恢复数据库的一致性状态。

日志由多个日志记录组成,每条日志记录对应一个重要操作,比如更新数据、删除数据、提交事务等,这些操作往往会改变数据库的一致性状态。日志空间最初在内存中由缓冲区管理器分配,日志记录则由日志管理器负责创建,缓存中的日志记录会被尽快写到持久性存储介质中。记录事务操作的几种日志记录类型如下。

[START T]:表示事务T开始。

[COMMIT T]:表示事务T已经完成。[COMMIT] 记录不能保证数据已经更新到磁盘上,如果需要的话应由日志管理器控制事务的逻辑。

[ABORT T]:表示事务T无法完成,需要终止。如果事务终止,那么它所做的任何更改都不能写到磁盘上,如果已经写到磁盘就必须消除这些影响。

[T, X, v]:Undo 日志的一条更新记录,表示事务T改变了元素 X,它的原值是 v。更新记录在数据库对内存执行 WRITE 操作时产生,不需要记录数据库元素的新值。

事实上日志记录的类型还有很多,涉及的操作也不限于插入、更新、删除等基础操作,本篇中我们只考虑对已有数据的更新操作。

Redo 日志

Undo 日志有一个限制,即我们在将事务对数据的修改刷写到磁盘前不能提交该事务。这样做可能会导致事务因为等待磁盘 IO 而被阻塞,也会占用较多的磁盘带宽。此外,由于每次故障恢复都要把相关数据恢复到事务之前的状态,即便这些数据已经部分或全部更新到磁盘了,这样反复修改岂不是浪费了很多资源。

事实上只要有日志用于恢复数据,那么把修改的数据暂存在主存中是安全的,并非一定要马上同步到磁盘。(重做)日志就是这样一种日志,它不需要等待数据写到磁盘就可以提交事务。

Redo与 Undo 日志的区别:

Undo 日志在恢复时撤销未完成事务的操作并忽略已提交事务,而 Redo 日志忽略未完成事务并重做已提交的事务。

Undo 日志要求先将修改后的数据写到磁盘再写入 COMMIT 日志记录,而Redo日志要求我们先写入 COMMIT 日志记录再将修改后的数据写到磁盘。

在使用 Undo 日志时,我们记录的是数据库元素的旧值,在使用 Redo 日志时,我们记录的是数据库元素的新值。

实际使用中,将两者相结合,日志记录[T, X, v, w]其中v是事务修改前的旧值,w是事务修改后的新值。

日志规则:

OceanBase 数据库遵循 WAL(write-ahead logging)原则。在事务T对数据库元素X的修改持久化到磁盘前,日志记录[T,X,V,w]必

须刷写到磁盘上。[COMMITT]记录一旦出现在日志中就必须被刷写到磁盘上。

异常宕机恢复:

Redo:按照从前往后的顺序,重做所有已提交的事务。

Undo:按照从后往前的顺序,撤销所有未提交的事务。

日志不可能无限制的增长,宕机恢复不允许此情况发生。所以就需要进行“过时”日志的清理,宕机恢复时,让日志恢复应用的时间缩短。那怎么识无用日志呢,是不是事务t1时刻commit后,t1时刻之前的事务都是“过时”日志了?对于

单线程的系统,同一时刻只有一个事务执行,这当然是可以的;但是对于多线程的系统,这就不适用了。因此引入了检查点机制。

动态检查点创建

1.写入日志记录[START CKPT(T1,. Tk)]并刷写日志,其中 T1 到 Tk是当前所有的活跃事务。

2.将缓冲区的所有脏数据写到磁盘(可以容忍未提交事务的脏数据写到磁盘)。

3.写入记录[END CKPT] 并刷写日志。

动态检查点恢复:(从后往前扫描日志)

1.先遇到[END CKPT]记录,向前扫描到[START CKPT(T1,…

Tk)]记录,重做遇到的已提交事务。

2.先遇到 [START CKPT(T1,…… Tk)]记录,向前扫描直到前一条[START CKPT(S1,… Sn)]记录,重做遇到的已提交事务。

3.撤销遇到的未完成事务,如果T1.…Tk中仍然存在更早开始的未完成事务 Ti,继续扫描直到最早的[START Ti]记录,撤销这些未完成事务。

参考文献:

https://open.oceanbase.com/course/detail/9256

Logo

了解最新的技术洞察和前沿趋势,参与 OceanBase 定期举办的线下活动,与行业开发者互动交流

更多推荐