基本原理
在数据库的运行过程中,难免会遇到各种非预期的问题,例如:
硬件错误,例如突然断电、磁盘错误、有人拔了你的内存条 :P
软件问题,例如操作系统崩溃、数据库内部存在bug等等
操作错误,例如误删数据、插入了不符合预期的数据、应用程序异常等等
… …
在这些情况下,我们不希望我们的数据异常甚至丢失,有的情况下我们不能进行修复,例如火灾(这类问题依赖于备份存储介质的方式解决,需要异地容灾),但有的情况下我们可以进行解决,例如断电、崩溃。我们希望当数据库重新启动时,能够恢复其崩溃的那一瞬间的状态,能够恢复出“一致的”、“完整的”数据。
由于内存是易失性的,当数据库发生断电、崩溃等情况时,存储在内存中的数据会丢失,因此不能寄希望于存储在内存中的数据,我们希望找到一种方式,能够帮助数据库系统完成崩溃恢复,同时不那么影响性能。
REDO | UNDO | |
---|---|---|
未提交事务 | 不允许未提交的数据写入 | 允许未提交的数据写入(Steal) |
已提交事务 | 已提交的数据可以延迟写入 | 已提交的数据必须写入(Force) |
优点 | 可以延迟数据写入,减弱随机写 | 可以直接inplace修改,减少膨胀 |
当崩溃发生时,在重启的时候,恢复管理器就会开始工作,它会读取事务的状态,将已经提交的数据重新回放,将已经放弃或者中断的事务进行回滚,将数据库内不一致的数据恢复到一致的状态。在恢复的时候,恢复管理器有一套算法逻辑在其中,决定如何进行回放,大名鼎鼎的ARIES就是这方面的一个算法。 ARIES的算法,是IBM提出的一整套关于日志记录和恢复处理的算法,后续的数据库管理系统都多少参考了该算法。 可以预见的是,如果数据库长时间运行了很久,突然崩溃了,在重启的时候可能需要从数天前开始进行恢复,需要花费数个小时甚至上天的时间。这时候需要使用到检查点技术,将脏数据刷入到磁盘中,记录检查点刷下的最旧的数据页的,可以保证我们在恢复的时候从相对较新的位置开始。同时让我们可以清理掉旧的日志文件(或者复用),让日志不会无限制地增长。
日志所提供的功能不仅于崩溃恢复,它还能提供复制(包括主备复制、外部订阅复制等)、主备状态同步、按时间点还原等功能。
实现简述
在记录日志时- 每个数据页面 (堆或索引) 都标有影响页面的最新XLog记录的LSN
- 在缓冲区管理器能够写出一个脏页面之前,它必须确保XLog已经被刷新到磁盘,至少达到页面的LSN
LSN检查仅存在于共享缓冲区管理器中,不存在于临时表使用的本地缓冲区管理器中,因此,对临时表的操作不能被 WAL记录。 XLog:T