3. 事务与日志机制

Oracle 的备份恢复能力并不是靠“多复制几份文件”实现的,而是建立在一套严密的事务与日志机制之上。理解 UNDO、REDO、SCN、检查点以及实例恢复与介质恢复的分工,才能判断在什么场景下该用 RMAN 全备、增量备、归档日志备份,以及为什么归档日志一旦缺失,某些恢复路径就彻底走不通。

UNDO:保证读一致性与回滚

UNDO 表空间保存的是数据被修改前的旧值。当一个事务更新某行时,Oracle 先把该行旧值写入 UNDO 段,再修改数据块。UNDO 至少承担三项职责:一是事务回滚时把数据块还原;二是为其他会话提供一致性读(CR 块),使长查询看到的是查询开始时刻的版本;三是支撑闪回查询、闪回表等特性。

UNDO 与备份恢复的关系常被误解。UNDO 数据本身通常不是恢复的目标,因为实例恢复和介质恢复都依赖 REDO 重放来重建数据块,而不是靠 UNDO 反向修补。但 UNDO 表空间损坏会导致数据库无法打开或大量 ORA-01555,因此它仍应纳入常规备份范围。关键判断是:UNDO 决定“运行期能否一致读与回滚”,REDO 决定“故障后能否前滚重放”,两者不可互相替代。

REDO:前滚重放的唯一依据

REDO 记录的是“数据块发生了什么改变”,包括变更向量(change vector)和重做记录。它由两部分组成:联机重做日志(online redo log)和归档重做日志(archived redo log)。联机日志循环使用,写满后由 ARCn 进程归档为归档日志。只要 REDO 完整,Oracle 就能把数据文件前滚到任意一个 SCN 对应的状态。

这正是备份恢复策略的核心约束:数据文件备份 + 归档日志 = 可恢复到任意时间点;只有数据文件备份 = 只能恢复到备份时点。因此生产库必须开启 ARCHIVELOG 模式,并保证归档日志有独立、可靠的备份与保留策略。下面用一张信号链图展示一次事务从修改到可恢复的完整链路。

事务修改 → REDO 落盘 → 归档 → 可恢复性链路 事务 DML UPDATE / INSERT UNDO 段 旧值 / 回滚 / CR 数据块 Buffer 脏块(未落盘) REDO Buffer 变更向量 CV LGWR 提交即写日志 联机重做日志 循环复用 ARCn 归档 ARCHIVELOG 模式 归档日志 可备份 / 可保留 恢复能力 数据文件 + 归档 → 任意时间点 仅数据文件 → 仅备份时点 生成 写旧值 写入 刷出 前滚

SCN:贯穿始终的逻辑时钟

SCN(System Change Number)是 Oracle 内部的单调递增逻辑时钟,用来标记数据库在某一时刻的一致性状态。每个提交事务都会推进 SCN,数据块头部记录块最后一次变更的 SCN,控制文件记录检查点 SCN,数据文件头记录文件检查点 SCN。恢复的本质,就是把数据文件从当前 SCN 前滚到目标 SCN。

常用观察方式如下:

-- 当前 SCN
SELECT CURRENT_SCN FROM V$DATABASE;

-- 数据文件检查点 SCN 与状态
SELECT file#, checkpoint_change#, status, fuzzy
FROM   V$DATAFILE_HEADER;

-- 控制文件中的检查点信息
SELECT checkpoint_change#, controlfile_type
FROM   V$DATABASE;

判断恢复起点的关键,是比较数据文件头 SCN 与控制文件/归档日志中的 SCN。若数据文件头 SCN 落后,就需要从该 SCN 之后的重做记录开始前滚;若数据文件头 SCN 比控制文件还新(例如用旧控制文件恢复),则会出现 ORA-01190 一类错误,必须换用匹配的控制文件或执行不完全恢复。

检查点:缩短恢复窗口

检查点(Checkpoint)的作用是触发 DBWn 把脏块写盘,并记录“截至此 SCN 的数据块已持久化”。检查点越频繁,实例崩溃后需要前滚的 REDO 越少,恢复越快;但频繁检查点会增加 I/O。Oracle 提供多种检查点:完全检查点、增量检查点、局部检查点。其中增量检查点通过 CKPT 进程持续推进检查点队列,避免日志切换时集中写盘造成停顿。

对备份策略的影响在于:检查点位置决定了实例恢复的起点。如果检查点推进正常,实例恢复通常只需重放少量 REDO;如果检查点长期不推进(例如 DBWn 写盘受阻),崩溃恢复时间会显著拉长。因此监控 V$INSTANCE_RECOVERY 中的 ESTIMATED_MTTR 很有价值。

实例恢复与介质恢复的分工

实例恢复(Instance Recovery)发生在实例异常终止后,由 SMON 自动完成,分两步:先前滚(Roll Forward),把联机日志中的重做记录应用到数据文件,使数据达到崩溃前状态;再回滚(Roll Back),利用 UNDO 撤销未提交事务。实例恢复不需要人工干预,也不需要归档日志,因为联机日志足够覆盖崩溃点。

介质恢复(Media Recovery)发生在数据文件丢失、损坏或需要恢复到历史时间点时,必须由 DBA 主动执行。它又分为完全恢复和不完全恢复:完全恢复用备份数据文件加归档日志前滚到最新 SCN;不完全恢复则指定时间点、SCN 或日志序列号停止,之后必须 RESETLOGS 打开数据库,产生新的日志序列。

对比项实例恢复介质恢复
触发原因实例崩溃、SHUTDOWN ABORT数据文件损坏、丢失、误删
执行者SMON 自动DBA 手动(RMAN / SQL*Plus)
依赖日志联机重做日志归档日志 + 联机日志
是否需备份不需要需要数据文件备份
典型命令无(自动)RECOVER DATABASE

对备份恢复策略的直接影响

基于上述机制,可以归纳出几条硬性策略:第一,生产库必须运行在 ARCHIVELOG 模式,否则只能做冷备且无法前滚;第二,归档日志必须与数据文件备份分开存放并定期备份,因为它们是介质恢复的“燃料”;第三,定期执行 RMAN 全备加增量备,并配合 BACKUP ARCHIVELOG ALL,才能覆盖任意时间点恢复;第四,控制文件必须自动备份(CONFIGURE CONTROLFILE AUTOBACKUP ON),否则恢复时缺少 SCN 与日志序列的映射依据;第五,UNDO 表空间要保证足够大且纳入备份,避免恢复后因 ORA-01555 导致查询失败。

判断一个库能否做“任意时间点恢复”,只需问两个问题:归档日志是否连续完整?控制文件与数据文件是否来自同一备份链?两者缺一,恢复目标就只能退回到备份时点。

理解 UNDO、REDO、SCN、检查点与两类恢复的关系后,后续设计备份方案时就不会只盯着“备份频率”,而会同时关注归档连续性、检查点推进情况和恢复窗口估算,这才是工程化的备份恢复思维。