v$dataguard_stats 的 apply lag 是估算值,不可信;真实延迟需通过主备库 scn 差值除以 scn 增速计算,并确认 mrp0 状态为 applying_log 且 block# 持续增长,同时启用 real-time apply(需 standby redo log 和 using current logfile)。
查 v$dataguard_stats 的 apply lag 值不等于真实延迟
这个视图返回的 apply lag 是估算值,依赖后台统计周期和 scn 增速模型,不能反映你执行 select 时是否真能查到刚提交的数据。它可能显示 “+00 00:00:00”,但你一查主库刚 commit 的记录,还是空的。
关键要看三样东西是否同步:TIME_COMPUTED、DATUM_TIME 和当前系统时间。如果 TIME_COMPUTED 是几分钟甚至几小时前的值,那这个 apply lag 就是“死数据”,别信。
更可靠的做法是直接比对 SCN:
- 主库立刻执行:
SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER FROM DUAL; - 备库**1 秒内**执行同样语句
- 差值 ÷ 当前 SCN 增速(查
V$DATAGUARD_STATS中estimated startup time对应的每秒增量,通常 1~5 万/秒)≈ 实际延迟秒数
V$MANAGED_STANDBY 里看 MRP0 状态才是真干活信号
只靠 OPEN READ ONLY 不代表数据在动。必须确认 MRP0 进程真实运行且处于应用态。
执行:SELECT PROCESS, STATUS, SEQUENCE#, BLOCK# FROM V$MANAGED_STANDBY WHERE PROCESS = 'MRP0';
要满足两个条件才算有效应用:
-
STATUS必须是APPLYING_LOG(不是WAIT_FOR_LOG、WAIT_FOR_GAP或IDLE) -
BLOCK#必须持续增长(隔几秒再查,数值变大)
如果 STATUS 是 WAIT_FOR_LOG,说明 MRP 在等主库把当前联机日志归档完才动手——这不是卡住,是默认行为;想让它实时拉 current logfile,得配 standby redo log 并启用 real-time apply。
启用 real-time apply 后,MRP0 才可能真正追上主库 SCN
Oracle 11g 物理备库默认不启用实时应用,即使归档日志已传到,MRP0 也只在日志“写满”后才开始应用。主库刚 COMMIT 的重做记录还在联机日志末尾,备库根本没读到。
启用 real-time apply 的前提和操作:
- 备库必须有可用的 standby redo log(
V$STANDBY_LOG中STATUS≠UNASSIGNED) - 备库处于
READ ONLY WITH APPLY状态(不是单纯READ ONLY) - 执行:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;
注意:这条命令会终止原有 MRP 进程并重启。如果之前卡在 gap,得先用 V$ARCHIVE_GAP 补全缺失归档,否则新 MRP 仍会停在原地。
别被 STANDBY_MAX_DATA_DELAY 参数误导
这个参数只影响 V$DATAGUARD_STATS 中 apply lag 的报告值,比如设成 30,系统就“假装”延迟不超过 30 秒,但它对实际查询可见性完全没作用。
真正决定“查得到 / 查不到”的,只有当前备库已应用的 SCN 是否 ≥ 主库提交那一刻的 SCN。哪怕 STANDBY_MAX_DATA_DELAY=0,只要 MRP0 没跑起来、没启 real-time apply、或者 standby redo log 缺失,SCN 就不会动,查询就必然滞后。
最容易被忽略的是:开了 READ ONLY WITH APPLY,却没加 USING CURRENT LOGFILE —— 此时 MRP0 状态可能是 APPLYING_LOG,但 BLOCK# 长期不动,因为它其实在等归档写满,而不是在实时消费 current logfile。











