03-数据库启动失败排查 讲了"怎么分诊",本篇讲"怎么手术"。控制文件和控制着归档链的在线 redo 是 Oracle 最要命的两类文件——处理动作分支多、风险高,动手前先想清楚自己在归档模式还是非归档模式、有没有 RMAN 备份,这两个前提决定你能走哪条路。
一、控制文件丢失/损坏
1.1 为什么控制文件如此重要
控制文件是数据库的"户口本":数据文件清单、redo 清单、RMAN 备份目录、SCN 时间线全在里面。丢失意味着数据库连"自己有哪些家当"都不知道。
它也是少数 Oracle 官方要求多路复用的文件:control_files参数指向 3 份副本(建议分布在不同磁盘),任一副本损坏,其余副本仍可救场。
1.2 场景 A:多路复用副本损坏(最常见,也最轻松)
-- ① 关库SQL>SHUTDOWNIMMEDIATE;-- ② 用好副本覆盖坏副本(OS 层操作)$ cp/u02/ctl/control02.ctl/u01/ctl/control01.ctl-- ③ 起库SQL>STARTUP;alert.log 里出现单个控制文件副本 IO 错误时就是这么处理。做完必须排查坏副本所在磁盘——多路复用的意义就是"不同故障域",如果三份都放同一块盘,等于没复用。
1.3 场景 B:全部损坏,有 RMAN 备份(标准路径)
前提:CONFIGURE CONTROLFILE AUTOBACKUP ON;(没开?现在就去开)。
RMAN> STARTUP NOMOUNT; -- 控制文件丢了,只能到这 RMAN> SET DBID <你的DBID>; -- 从之前的告警/文档里找;RAC 常见自动识别失败时必需 RMAN> RESTORE CONTROLFILE FROM AUTOBACKUP; RMAN> ALTER DATABASE MOUNT; RMAN> RECOVER DATABASE; -- 用归档+redo 恢复数据文件 RMAN> ALTER DATABASE OPEN RESETLOGS; -- 重建的控件文件使 redo 序列归零RESETLOGS 的代价:在线日志序列号从 1 重新计数,之前的所有备份瞬间作废——所以 OPEN RESETLOGS 之后要立刻做一个全新的全备。
1.4 场景 C:无备份,但有 trace(最后手段)
前提:曾经执行过ALTER DATABASE BACKUP CONTROLFILE TO TRACE,或从 alert.log 中整理出 CREATE CONTROLFILE 语句:
-- 平时(预防措施)就做一份:SQL>ALTERDATABASEBACKUPCONTROLFILETOTRACEAS'/tmp/ctrl_rebuild.sql';拿到重建脚本后按其中 NORESETLOGS/RESETLOGS 两个分支选择执行(数据文件都在、只是控制文件丢了 → 尽量走 NORESETLOGS 分支,保住归档链)。
1.5 控制文件丢失决策树
控制文件损坏 ├─ 还有副本可用? │ └─ 是 → 好副本覆盖 → 开库 → 排查磁盘 → 完事 └─ 全没了 ├─ 有 RMAN autobackup?→ RESTORE CONTROLFILE → RECOVER → OPEN RESETLOGS → 立刻全备 ├─ 有 trace 重建脚本?→ CREATE CONTROLFILE(优先 NORESETLOGS) └─ 都没有?→ 数据文件还在 → 手写 CREATE CONTROLFILE(高风险)二、在线重做日志(Online Redo Log)丢失
2.1 先看状态,状态决定动作
SELECTgroup#, status, archived, member FROM v$logfile;SELECTgroup#, status, sequence# FROM v$log;| 组状态 | 含义 | 丢失后果 | 处理 |
|---|---|---|---|
| UNUSED | 从未写过 | 无数据丢失 | 直接CLEAR LOGFILE |
| INACTIVE | 检查点已推进过它 | 无数据丢失,但对应归档可能缺失 | CLEAR LOGFILE(归档模式下可能要先处理归档) |
| ACTIVE | 崩溃恢复还可能需要它 | 危险 | CLEAR UNARCHIVED LOGFILE,会打断归档链 |
| CURRENT | LGWR 正在写 | 极危险,可能丢数据 | 需 RMAN 不完全恢复 |
| 全部丢失 | — | 数据丢失风险高 | RESETLOGS 重建 |
2.2 各状态处理命令
-- INACTIVE / UNUSED:安全清理重建SQL>ALTERDATABASECLEAR LOGFILEGROUP3;-- ACTIVE 且归档模式下归档也没了:跳过归档强制重建SQL>ALTERDATABASECLEAR UNARCHIVED LOGFILEGROUP3;CLEAR UNARCHIVED的连锁后果:该组对应的归档日志永久缺失,这条归档链断了——此后用它之前的备份做恢复,最多只能恢复到断点之前。清完必须立刻全备,重新建立恢复基线。Data Guard 环境下还要检查备库是否因此出现 gap。
2.3 CURRENT 组丢失:接受不完全恢复
CURRENT 日志里有尚未检查点化的数据,物理丢失即丢数据。标准动作是 RMAN 不完全恢复:
RMAN> RESTORE DATABASE; RMAN> RECOVER DATABASE UNTIL CANCEL; -- 归档应用完手动 CANCEL RMAN> ALTER DATABASE OPEN RESETLOGS;纪律:做完 RESETLOGS,第一时间全备 + 通知业务核对数据一致性。
2.4 预防:日志组的"三三制"
- 每个日志组至少 2 个 member,分布在不同磁盘(和 control file 同理);
- 至少3 个组,为切换留余量;
- redo 大小以30 分钟左右切换一次为宜(切换过快 → checkpoint 压力 +
log file switch等待,见 08-log-file-sync提交慢专题)。
三、两条贯穿全文的保命配置
-- RMAN 里执行:控制文件+spfile 自动备份RMAN>CONFIGURE CONTROLFILE AUTOBACKUPON;-- 日常留档:控制文件重建脚本(每月或重大变更后)SQL>ALTERDATABASEBACKUPCONTROLFILETOTRACEAS'/backup/ctrl_rebuild.sql';这两条配置的价值在 03-数据库启动失败排查 的参数文件场景和本篇的场景 B/C 中反复兑现——恢复的难度取决于事故发生前你做了什么。
四、演练建议(在测试库)
下面是一套安全的故障演练方法(与 RAC 实操演练同款流程),单机同样适用:
- 演练前先备份:
ocrconfig -manualbackup(集群)或 RMAN 全备(单机); - 制造故障:
dd if=/dev/zero of=<测试盘> bs=1M count=50模拟文件损坏; - 按 1.5 / 2.1 的决策树走恢复流程;
- 验收:开库后核对数据 + 检查 alert.log 无新 ORA-。
只在隔离的测试环境做。
五、小结
- 控制文件:有副本→覆盖;有 autobackup→RESTORE+RESETLOGS;有 trace→CREATE CONTROLFILE;
- 在线日志丢失先查
v$log状态:UNUSED/INACTIVE 可 CLEAR,ACTIVE 要 UNARCHIVED(断归档链,清完立刻全备),CURRENT 走不完全恢复; - 两条保命配置:
CONTROLFILE AUTOBACKUP ON+ 定期 TO TRACE; - RESETLOGS 之后旧备份作废,必须立即全备。
下一个大主题是性能:06-AWR-ASH-ADDM性能诊断三板斧 —— 5 分钟读懂一份 AWR。