数据库系统(六)
参考资料:
《数据库系统概论》| 第十章 数据库恢复技术 知识梳理-腾讯云开发者社区-腾讯云
5.6 数据库恢复技术
恢复技术的核心思想就四个字:“冗余备份”。
无论怎么恢复,都必须依赖日志或转储的冗余数据。
1. 故障类型
事务内部故障
事务执行到了一半因为自身逻辑错误(如除数为0、死锁被选中回滚)无法继续。
特征:
仅影响该事务本身,不影响整个数据库。
不需要 DBMS 动用恢复子系统,事务自身的回滚机制就能解决。
系统故障(软故障)
如突然断电、操作系统崩溃、DBMS 进程被杀。
特征:
内存(缓冲区)数据全部丢失,但磁盘上的数据库文件完好无损。
这会导致两种情况:
有些事务没提交就崩了(改了内存没写盘);
有些事务提交了但没来得及写盘就崩了。
介质故障(硬故障)
如硬盘损坏、强磁场干扰。
特征:
磁盘上的物理数据库文件被破坏了(数据真没了)。
这是最严重的故障,必须结合“日志文件”+“后备副本(转储文件)”才能恢复。
2. 恢复策略的底层支撑
日志文件
日志先写原则
在把修改后的数据块写到磁盘数据库之前,必须先把描述这个修改的日志记录写到磁盘日志文件中。
原因:
写日志是追加写,速度极快;
写数据块是随机写,速度慢。
如果先写数据断电了,日志里没记录,恢复时就没有凭证了。
日志记录的内容
事务标识、操作类型、操作对象、修改前值(旧值,用于Undo)、修改后值(新值,用于Redo)。
转储(备份)
针对介质故障。DBA 定期把整个数据库拷贝下来。
1)静态转储
转储期间不允许任何事务操作(数据库只读),数据一致性好,但影响业务。
2)动态转储
转储期间允许事务操作,不阻塞业务,但转储出来的副本可能不一致,必须配合日志文件才能恢复到一致状态。
3. 恢复机制:Undo 与 Redo 的精准判定
发生系统故障重启后,DBMS 扫描日志,会根据事务的最后状态采取不同动作:
Undo(撤销)
触发条件
扫描到某个事务没有 Commit 记录(说明它崩在了执行中途)。
动作
利用日志中的“修改前值(旧值)”,反向操作,把该事务已经做过的修改全部抹平。
目的
消除未提交事务对数据库的修改,保证原子性。
Redo(重做)
触发条件
扫描到某个事务有 Commit 记录(说明它已经成功结束,只是数据可能还停留在内存缓冲区没刷到磁盘)。
动作
利用日志中的“修改后值(新值)”,正向操作,把该事务的修改重新执行一遍写到磁盘。
目的
把已提交但未落盘的数据挽救回来,保证持久性。
不管(Ignore):对于既没有Commit,也没有任何操作记录的事务,直接跳过。
4. 检查点技术
为什么需要:
系统故障恢复时,如果不加优化,DBMS 要从日志文件的第一条记录开始扫描,判断每个事务是 Redo 还是 Undo。
系统运行几年,日志几百个G,重启一次要几小时。
检查点的工作原理
DBMS 周期性地(如每5分钟)做以下动作:
暂停接受新事务。
将当前内存中所有已提交事务的修改,强制刷入磁盘数据库。
在日志文件中写入一条“检查点记录”(记录此刻活跃的事务列表)。
检查点就像游戏里的“自动存档点”,只要过了存档点,之前的事情就当它已经安全落盘了,死了重开(重启恢复)只需要从最近的存档点往前回溯一点点就行了。
基于检查点的恢复策略
发生系统故障重启时,恢复过程大幅缩短:
从后往前扫描日志,找到最近一个检查点记录。
建立两个队列:
1)Redo 队列(在检查点前已提交但可能没刷盘的事务)
2)Undo 队列(在检查点时还没提交的事务)。
从检查点时刻开始正向扫描日志(抛弃检查点之前的日志不看!):
1)遇到 Commit 的,加入 Redo 队列。
2)遇到没 Commit 的,加入 Undo 队列。
3)先做 Undo:把未提交的修改抹掉。
4)再做 Redo:把已提交的修改重做一遍。