必须开启 FORCE LOGGING,否则 NOLOGGING 操作必然导致备库软坏块(ORA-01578/ORA-26040);执行 ALTER DATABASE FORCE LOGGING 并验证 V$DATABASE.FORCE_LOGGING 为 YES;需定期检查 UNRECOVERABLE_CHANGE# 及 NOLOGGING 对象,不可依赖其“一劳永逸”。
FORCE LOGGING 必须开,否则 NOLOGGING 操作必然导致备库坏块
主库不开启 force logging,只要执行了任何 nologging 操作(比如 create index …… nologging、insert /*+ append */、impdp …… transform=disable_archive_logging:y),备库对应数据块在首次访问时就会报 ora-01578 + ora-26040 ——这不是概率问题,是确定性坏块。oracle 官方文档 id 1623284.1 明确指出:这类坏块属于“soft corrupt”,不会被 rman 备份检测或拦截,但会在查询时直接暴露。
怎么开?一条命令,但必须验证是否生效
执行:ALTER DATABASE FORCE LOGGING;
之后立刻验证:SELECT FORCE_LOGGING FROM V$DATABASE;
返回值必须是 YES。常见误操作包括:
- 在 RAC 环境中只在一个实例执行,未检查所有实例的
V$DATABASE(实际是全局生效,但验证时建议查全部) - 执行后未重启监听或未触发日志切换,导致部分归档日志仍含 NOLOGGING 记录(无需重启库,但建议手动
ALTER SYSTEM SWITCH LOGFILE;) - 误以为表空间级
FORCE LOGGING足够(它不能覆盖数据库级NO FORCE LOGGING的失效风险)
开了 FORCE LOGGING 就万事大吉?不是
FORCE LOGGING 只能保证 redo 日志里记录完整变更,但它不阻止用户显式写 NOLOGGING,只是让该关键字失效。真正要排查隐患,得主动扫描:
SELECT OWNER, TABLE_NAME, LOGGING FROM DBA_TABLES WHERE LOGGING = 'NO';SELECT OWNER, INDEX_NAME, LOGGING FROM DBA_INDEXES WHERE LOGGING = 'NO';
这些对象本身是 NOLOGGING 属性,但只要库处于 FORCE LOGGING,它们的操作仍会被强制记全量日志。可一旦某天误执行 ALTER DATABASE NO FORCE LOGGING;,这些对象立刻变成高危源。所以定期检查 V$DATAFILE.UNRECOVERABLE_CHANGE# 更关键:SELECT NAME, UNRECOVERABLE_CHANGE#, TO_CHAR(UNRECOVERABLE_TIME, 'YYYY-MM-DD HH24:MI') FROM V$DATAFILE WHERE UNRECOVERABLE_CHANGE# > 0;
只要某 datafile 的 UNRECOVERABLE_CHANGE# 非零,就说明它已被 NOLOGGING 操作污染过——这个数字不会自动清零,也不会因开启 FORCE LOGGING 而倒退。
11g 和 19c 的修复方式完全不同,别混用
如果已经发生坏块,恢复路径取决于版本:
- Oracle 11g/12.1:必须停 MRP,从主库拷整个 datafile 到备库,再
ALTER DATABASE DATAFILE …… ONLINE;——耗时长、中断久 - Oracle 12.2+(尤其 19c):备库停 MRP 后,直接运行
RMAN> RECOVER DATABASE NONLOGGED BLOCK;即可定位并修复受影响块,无需替换整个文件。前提是备库已启用V$NONLOGGED_BLOCK视图(默认开启)
注意:19c 下即使用了 impdp …… DISABLE_ARCHIVE_LOGGING:Y,只要主库是 FORCE LOGGING,该参数也会被忽略 —— 这点和旧版本行为不一致,容易误判。
最常被忽略的一点:FORCE LOGGING 开启后,对性能有轻微影响(redo 体积增大 3%~8%,取决于 workload),但比起备库不可用、需要人工介入恢复的代价,这点开销几乎可以忽略。真正该警惕的,是把它当成“一劳永逸”的开关,而忘了定期核对 V$DATAFILE.UNRECOVERABLE_CHANGE# 和清理历史 NOLOGGING 对象。






























