SCN 不一致的本质、文件头机制与 event 21307096 的正确使用姿势
一、问题本质:这不是“恢复失败”,而是
时间线断裂
本次问题的表象是:
- ORA-01113 / ORA-01110
- 数据文件头不一致
- 恢复完成但无法 open
- 最终实例异常终止
但真正的问题并不是“恢复没做完”,而是:
数据库各组件的时间线(SCN)已经不在同一个因果链上
二、存储架构是“事故的第一原因”
2.1 实际部署结构
-
控制文件、部分系统相关文件:
→ VMware 虚拟磁盘
-
业务数据文件:
→ 裸金属盘(直通 / 独立存储)
2.2 快照回退发生了什么
VMware 快照只对虚拟磁盘生效:
| 组件 | SCN |
|---|---|
| 控制文件 | T-1 |
| 虚拟盘上的数据文件 | T-1 |
| 裸金属数据文件 | T |
从 Oracle 的视角看,这是一个逻辑上不可能存在的状态:
- 控制文件认为:数据库停在 T-1
- 裸金属数据文件头却声明:我已经推进到 T
这不是“需要介质恢复”,
而是时间被撕裂了。
三、Oracle 启动阶段做了哪些一致性校验
理解这一点,是判断“还能不能救”的关键。
3.1 核心校验对象
Oracle 在 open 阶段至少会对以下 SCN 进行交叉验证:
- 控制文件中的 checkpoint SCN
- 数据文件头的 checkpoint SCN
- redo / archivelog 能否覆盖 gap
- SYSTEM / UNDO 等关键文件的一致性
3.2 为什么 recover database 会“完成”,但还是 open 失败
这是很多 DBA 容易误判的地方。
SQL> recover database
Media recovery complete.
这句话不代表“一切 OK”,它只说明:
从控制文件视角看,
所需 redo 已经 apply 完毕
但问题是:
- redo 是基于 T-1 的控制文件
- 裸金属数据文件已经在 T 的未来
你在做的不是“补日志”,
而是试图用过去的时间线去解释未来的数据状态。
四、当时可选的两条“暴力路线”,以及为什么会犹豫
4.1 BBED:直接修改数据文件头
本质动作:
- 手工修改数据文件头中的:
- checkpoint SCN
- fuzziness 标志
- 相关校验字段
理论上可行,但存在两个致命问题:
- 文件头结构高度依赖版本
- 11g 的经验不能直接套 19c
- 字段偏移、校验方式都有变化
- 一旦改错,文件直接“不可解释”
- 不是 recover 不了
- 而是彻底报废
在生产事故中,BBED 是“最后的最后一条路”。
你当时的犹豫是完全正确的。
4.2 DUL:绕过 Oracle 内核,抽取数据
DUL 的核心思想是:
- 不信任控制文件
- 直接解析数据块结构
- 把“还能读懂的东西”捞出来
优点:
- 不依赖 SCN
- 不依赖控制文件一致性
缺点:
- 极度耗时
- 操作复杂
- 本质是“数据级逃生”,不是数据库级恢复
你走这条路,说明当时判断是:
内核层可能已经无解,只能保数据
五、真正的 19c 解法:event 21307096 的意义
事后复盘,真正适用于 19c 场景 的方案是:
event = '21307096 trace name context forever, level 3'
5.1 这个 event 在干什么(核心逻辑)
简化理解:
允许数据库在 open / recovery 过程中推进 SCN,
接受“文件头来自未来”的事实
它并不是“修复数据”,而是:
- 放宽对 checkpoint SCN 的强一致校验
- 让 recovery 能“追上”数据文件头
- 给数据库一个重新建立一致性的机会
这也是为什么它只能在明确事故场景下使用,而不能作为常规手段。
六、完整可复用操作流程(19c)
6.1 确保控制文件可重建(非常关键)
SQL> alter database backup controlfile to trace;
定位 trace 文件:
SQL> oradebug setmypid
SQL> oradebug tracefile_name
这一步的意义不是“马上用”,
而是
确保你始终有退路
6.2 尝试 open,确认真实阻断点
SQL> alter database open;
典型报错:
- ORA-01113
- ORA-01110(SYSTEM01.DBF)
6.3 执行恢复
SQL> recover database;
注意:
这里“complete”并不代表问题解决,只是推进了一步。
6.4 遭遇 MAX_STRING_SIZE 的隐藏前置条件
再次 open:
SQL> alter database open;
触发:
- ORA-14694
- database must in UPGRADE mode to begin MAX_STRING_SIZE migration
这是一个与事故无关、但会阻断恢复路径的配置问题。
6.5 参数修正 + UPGRADE 打开
参数文件中补充:
MAX_STRING_SIZE=EXTENDED
然后:
SQL> alter database open upgrade;
至此,数据库才能进入可继续处理状态。
七、关键经验总结(比操作更重要)
7.1 VMware 快照 ≠ 数据库一致性点
在以下架构中:
- 虚拟盘 + 裸金属混用
- 没有存储级一致性快照
- 没有 RMAN 时间点恢复
任何“直接回退快照”的操作,本质都是在赌。
7.2 对 DBA 来说,更重要的是“判断还能不能救”
- ORA-01113 不是最危险的
- 真正危险的是:
- 控制文件与数据文件处于不同时间线
- redo 无法解释现有数据状态
7.3 19c 时代,不要盲目复用 11g 的“硬改经验”
-
BBED 仍然存在
-
但 event + 内核容错路径 才是更安全的选择
-
DUL 应该是:
“我已经不相信这个数据库还能 open 的时候”
八、一句话总结
这次事故的本质不是“恢复失败”,而是数据库被强行拉回了一个它从未存在过的时间点
在 19c 中,理解 SCN、文件头与内核容错机制,比会用多少工具更重要。




