数据库恢复¶
约 1797 个字 预计阅读时间 6 分钟
概述¶
-
故障是不可避免的,包括:硬件故障、软件错误、操作失误、恶意破坏等
-
故障的影响主要表现为:运行事务非正常中断、影响数据的正确性、数据丢失
故障的种类¶
-
事务内部的故障
- 事务故障主要是一些非预期的,运算溢出、死锁等
-
系统故障
- 称为软故障,造成系统停止运作,需要重新启动;数据库在内存里的缓存信息全部丢失
-
发生故障时,如果尚未完成的事务可能一部分结果已经写回数据库了,就需要UNDO所有未完成事务
-
发生故障时,已完成的事务结果可能部分或全部留在缓冲区,尚未写回,就需要REDO
-
介质故障:硬故障,外存损坏
-
病毒
恢复技术¶
- 建立数据冗余的常见方法:数据转储(backup),日志文件(logging)
转储方法
-
静态转储:数据库停止服务,期间不允许任何的access,然后进行转储
- 优点:实现简单;缺点:数据库可用性低
-
动态转储:转储操作与用户事务并发进行,期间允许access
-
优点:不用等待事务结束,不影响事务进行;缺点:不能保证副本的数据正确有效
-
还要将转储期间发生的事务以logging形式记录
-
登记日志文件¶
- 日志文件的格式:以log record为单位的日志文件,以block为单位的日志文件
-
以记录为单位的日志文件
log record的内容:
-
事务标识(txn_id)
-
操作类型(增删改查)
-
操作对象(记录内部标识)
-
insert_key-value, delete_key-value, old_key-value, new_key-value
-
-
以数据块为单位的日志文件
事务标识、被更新的数据块
登记日志文件遵循两条原则
-
登记的次序严格按照并发事务执行的顺序
-
必须先写日志文件,后写数据库
恢复策略¶
事务故障的恢复¶
-
事务故障:事务在运行至正常终点前被终止,恢复子系统利用日志文件撤销(UNDO)此事务对数据库的修改
-
恢复步骤:
-
反向扫描文件日志,查找该事务的更新操作
-
对该事务的更新操作执行逆操作
-
继续扫描,重复;直至读到此事务的开始标记,事务故障恢复就完成了
系统故障的恢复¶
-
系统故障:1. 事务未完成就已经把数据写回数据库;2. 事务完成了但是结果还在缓冲区
-
恢复方法:UNDO未完成的事务,REDO已完成的事务
-
恢复步骤:
-
正向扫描日志文件,找出故障发生前已经完成的事务,加入REDO队列;找出未完成的事务,加入UNDO队列
-
对撤销队列事务进行UNDO:反向扫描 + 逆操作
-
对重做队列事务进行REDO:正向扫描 + REDO
具有检查点的恢复技术¶
为什么提出checkpoint
- 我们在利用日志技术进行恢复时,有两个问题需要优化:
-
搜索整个日志需要耗费大量的时间
-
REDO需要耗费大量时间
- 解决方法:具有检查点(checkpoint)的恢复技术,在日志文件中增加检查点记录,系统中增加重新开始文件,
重新开始文件
checkpoint记录的内容
-
活动事务列表ATL(active transaction list):
- 记录在checkpoint开始时,所有正在进行中(已经开始但是没有提交或中止)的事务的列表;以及这些事务一个last log record的地址;
- 记录在checkpoint开始时,所有正在进行中(已经开始但是没有提交或中止)的事务的列表;以及这些事务一个last log record的地址;
-
各种相关的日志序列号(lsn):last_lsn, checkpoint_lsn
-
Dirty Page Table
分析阶段¶
-
找到最后一个检查点:recovery manager首先会找到日志中最近的checkpoint。这通常通过读取数据库控制文件或日志文件头部的一个特殊指针(有时称为“重新开始文件”或主记录中的指针)来实现,该指针指向检查点记录在日志中的位置 (LSN - 日志序列号)。
-
加载检查点信息:从该检查点记录中,恢复管理器加载以下信息:
-
活动事务列表 (Active Transaction Table - ATT):记录了在检查点开始时所有正在进行的事务及其最后一条日志的 LSN。
-
脏页表 (Dirty Page Table - DPT):记录了在检查点开始时,buffer pool中哪些数据页是脏的(已被修改但可能未写入磁盘),以及这些脏页的 recLSN(第一次使该页变脏的日志记录的 LSN)。
-
-
向前扫描日志:从找到的检查点记录的 LSN 开始,向前扫描日志文件,直到日志的末尾。
-
更新 ATT:
-
当遇到事务的 BEGIN 日志记录时,将该事务加入 ATT。
-
当遇到事务的 COMMIT 或 ABORT 日志记录时,将该事务从 ATT 中移除
-
更新 ATT 中事务的 lastLSN 为其遇到的最新日志记录的 LSN。
-
-
更新 DPT:
- 当遇到数据修改的日志记录(如 UPDATE, INSERT, DELETE)时,如果被修改的页不在 DPT 中,则将其加入 DPT,并记录其 recLSN 为当前日志记录的 LSN。如果已在 DPT 中,则不需要更新 recLSN(recLSN 记录的是 首次 变脏的 LSN)。
-
-
分析阶段结束时的成果:
-
得到一个准确的 ATT,包含了在系统崩溃时所有真正活动的事务。
-
得到一个准确的 DPT,包含了在系统崩溃时所有可能仍在内存中且为脏状态的页,以及它们最早变脏的日志记录位置 (recLSN)。
-
重做阶段¶
- 确保所有已提交事务的修改都已成功写入磁盘(持久性),并且将数据库恢复到崩溃发生时的确切状态
-
确定重做起点:
- 重做阶段的起始 LSN 通常是分析阶段确定的 DPT 中所有脏页的最小 recLSN。这意味着从这个最早可能未被持久化的修改开始重做。如果 DPT 为空(理论上,如果检查点后所有操作都落盘且没有新脏页),则可以从检查点 LSN 之后开始。
-
向前扫描日志并重做:从确定的重做起点 LSN 开始,再次向前扫描日志到末尾。
对于每一条数据修改的日志记录:
-
如果该记录影响的页 P 不在 DPT 中,则跳过此记录(因为这意味着该页在检查点时是干净的,并且之后没有再变脏,或者其修改已通过检查点或后续操作安全落盘)。
-
如果页 P 在 DPT 中,并且该页在磁盘上的版本(通过其存储的 PageLSN 判断)比当前日志记录的 LSN 旧,并且当前日志记录的 LSN 大于等于页 P 在 DPT 中的 recLSN,则重新执行 (Redo) 该日志记录所描述的操作。
-
重做操作后,将内存中页 P 的 PageLSN 更新为当前日志记录的 LSN。
-