确认备库NOLOGGING坏块需定期扫描:12.2+用RMAN VALIDATE DATABASE NONLOGGED BLOCK;12.1-用DBV或VALIDATE DATAFILE CHECK LOGICAL,并查V$DATABASE_BLOCK_CORRUPTION或V$NONLOGGED_BLOCK获取CORRUPTION_CHANGE#/NONLOGGED_START_CHANGE# SCN。

主库执行 NOLOGGING 操作后,备库大概率会出现逻辑坏块(NOLOGGING 坏块),这不是“同步慢了”或“日志没传完”的问题,而是根本性数据不一致——因为主库跳过了 redo 记录,备库靠应用 redo 构建数据块时,会得到一个空/无效/校验失败的块。必须主动识别并替换该块,不能等它被访问才暴露。
怎么确认备库真有 NOLOGGING 坏块?别只看告警
很多 DBA 看到备库报 ORA-01578 或 ORA-26040 才去查,其实已经晚了。正确做法是定期扫描:
- Oracle 12.2 及以上:直接用
RMAN> VALIDATE DATABASE NONLOGGED BLOCK;—— 这是专为NOLOGGING设计的校验命令,比VALIDATE DATABASE CHECK LOGICAL更精准,只扫可能缺失 redo 的块 - Oracle 12.1 及以下:用
DBV扫数据文件,但必须加FEEDBACK=1000控制输出量,否则日志爆炸;或用RMAN> VALIDATE DATAFILE n CHECK LOGICAL;,再查V$DATABASE_BLOCK_CORRUPTION - 查出来后,不要只记 file#/block#,一定要同步查
CORRUPTION_CHANGE#(11g/12c)或NONLOGGED_START_CHANGE#(12c+),这个 SCN 是定位增量备份起点的关键
RMAN 增量备份起点 SCN 怎么选?不是随便挑个大于 0 的数
增量备份的 FROM SCN 必须严格等于受影响数据文件的 FIRST_NONLOGGED_SCN,少一点就漏块,多一点就白备份。这个值只能从主库查:
SELECT FILE#, FIRST_NONLOGGED_SCN FROM V$DATAFILE WHERE FIRST_NONLOGGED_SCN > 0;
注意三点:
- 这个值是动态更新的:只要该数据文件里发生一次
NOLOGGING操作(比如INSERT /*+ APPEND */、CREATE TABLE AS SELECT),FIRST_NONLOGGED_SCN就会被设为那次操作开始时的 SCN - 如果多个文件都有值,要分别对每个文件做一次增量备份,不能合并成一个命令
- 查到 SCN 后,立刻在主库执行备份:
BACKUP INCREMENTAL FROM SCN 20606544 DATAFILE 4 FORMAT '/backup/inc_4_%U';—— 格式名带文件号,避免后续搞混
备库恢复时 offline for drop 和 online 的时机不能错
备库上操作顺序错了,会导致控制文件和数据字典状态不一致,轻则恢复失败,重则整个备库不可用:
- 先停 Redo Apply:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;,不是SHUTDOWN - 再 offline 数据文件:
ALTER DATABASE DATAFILE 4 OFFLINE FOR DROP;—— 必须加FOR DROP,否则后续RECOVER会报ORA-01139 - 注册完备份后,不能直接
ALTER DATABASE DATAFILE 4 ONLINE,得先取消恢复进程、再 online、再重启恢复:ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;→ALTER DATABASE DATAFILE 4 ONLINE;→ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;
为什么不能跳过增量备份,直接用主库全备重建备库?
可以,但代价太高:全备恢复耗时长、网络传输大、备库停机久。而 NOLOGGING 坏块通常只影响个别数据文件里的少量块,增量备份可能只有几十 MB。更关键的是——如果你没开 FORCE LOGGING,那主库随时可能再出一批 NOLOGGING 操作,下次还得重来。所以真正该补的不是这一次坏块,而是主库的配置:
- 立即在主库执行:
ALTER DATABASE FORCE LOGGING;,这会强制所有操作写 redo,包括APPEND - 检查现有表空间是否已启用:
SELECT TABLESPACE_NAME, FORCE_LOGGING FROM DBA_TABLESPACES;,没启用的补上:ALTER TABLESPACE users FORCE LOGGING; -
FORCE LOGGING有轻微性能开销(约 2–5%),但在 Data Guard 场景下,这是必须付出的成本











