根本原因是mrp0单线程无法并行处理ddl产生的海量redo,叠加备库i/o瓶颈、force logging未启用或主备补丁不一致,导致日志应用停滞;需检查v$managed_standby中block#推进、alert.log错误及补丁级别。

主库DDL触发重做日志膨胀,MRP单线程跟不上
Oracle 11g物理备库对DDL操作的同步延迟,根本原因不是“不支持DDL”,而是DDL生成的重做量远超常规DML——比如ALTER TABLE ... MOVE或CREATE INDEX会一次性产生数MB甚至GB级的redo,而11g的MRP0进程是单线程应用日志,无法并行处理这种大块连续变更。此时V$MANAGED_STANDBY中MRP0状态可能仍为APPLYING_LOG,但BLOCK#推进缓慢,V$DATAGUARD_STATS里apply lag持续上涨。
- 确认是否真由DDL引发:在主库执行DDL前后,对比
SELECT COUNT(*) FROM V$ARCHIVED_LOG WHERE FIRST_TIME > SYSDATE-1/24,若该时段归档数量突增5倍以上,大概率是DDL导致 - 11g不支持
PARALLEL APPLY,别指望通过参数开启多线程MRP——该功能直到12c R2才引入 - 避免在业务高峰期执行大DDL;如必须执行,优先用
NOLOGGING(注意:这会破坏DG一致性,仅限非关键表且已评估风险)
备库I/O成为瓶颈,尤其涉及索引重建类DDL
DDL常伴随大量索引维护、段扩展、位图块更新等物理写操作,这些在备库上同样要执行。11g默认未启用DB_FLASH_CACHE_FILE或DISK_ASYNCH_IO=TRUE时,备库磁盘I/O极易成为瓶颈,表现为wait event中db file sequential read或log file sync等待陡增,而V$SYSTEM_EVENT里average wait time超过20ms即需警惕。
- 检查备库I/O能力:运行
iostat -x 1 5,重点关注%util是否持续>90%、await是否>30ms - DDL期间禁用备库上的统计信息自动收集:
EXEC DBMS_STATS.LOCK_TABLE_STATS('SCHEMA','TABLE'),防止统计任务与MRP争抢I/O资源 - 若使用ASM,确保备库ASM磁盘组冗余级别与主库一致(如都为NORMAL),否则镜像同步会拖慢应用速度
主库FORCE LOGGING未启用,导致部分DDL redo丢失
这是最容易被忽略的隐性原因。即使主库是ARCHIVELOG模式,若未显式启用FORCE LOGGING,某些DDL(如CREATE TABLE AS SELECT带NOLOGGING)产生的redo可能不完整,备库MRP在应用时遇到坏块或SCN跳变,会主动暂停并等待人工干预,表现为MRP0状态卡在WAIT_FOR_LOG,且alert.log出现ORA-00316或ORA-00354错误。
- 立即验证主库:
SELECT log_mode, force_logging FROM v$database;,结果必须是ARCHIVELOG和YES - 若
force_logging为NO,执行ALTER DATABASE FORCE LOGGING;(注意:该操作需独占锁,建议在低峰期执行) - 补救已发生的GAP:查
V$ARCHIVE_GAP,手工拷贝缺失归档并用ALTER DATABASE REGISTER OR REPLACE PHYSICAL LOGFILE注册
11g跨小版本不兼容加剧DDL同步失败风险
11g对DDL的redo编码在不同PSU间存在细微差异。例如主库打了11.2.0.4.190115 PSU而备库仍是11.2.0.4.0,执行ALTER TABLE ... ADD COLUMN后,备库MRP可能解析到未知opcode,直接abort并退出,alert.log中出现control file version mismatch或ORA-00704。这不是延迟,而是同步中断,但现象常被误判为“延迟持续不恢复”。
- 严格比对主备库补丁级别:
SELECT banner FROM v$version WHERE banner LIKE 'Oracle%';,末尾字符串必须一字不差 - 检查
$ORACLE_HOME/OPatch/opatch lsinventory -detail,确认RDBMS组件补丁集完全一致 - 若已发生MRP静默退出,不要只看
ps aux | grep mrp——进程残留不代表运行正常;必须查V$MANAGED_STANDBY是否有MRP0记录,且STATUS为APPLYING_LOG
apply lag数字本身没用,得进V$MANAGED_STANDBY和alert.log看MRP到底卡在哪一步。











