WAIT_FOR_LOG的根因、是不是也可以failover、后续在主库异常关闭应该如何处理

WAIT_FOR_LOG的根因、是不是也可以failover、后续在主库异常关闭应该如何处理

结论先说

  • WAIT_FOR_LOG 的本质:备库把当前序列用完了,在等下一段 redo(可能是主库还没产生日志、传输暂时断了、或主库已经被关机),不等于有 GAP
  • 能不能在 WAIT_FOR_LOG 下切换可以,但要满足“无缺口(no gap)且可接受的 RPO”。若要 RPO=0,需满足同步传输 + 实时应用 + 无缺口;否则只能做 有损(IMMEDIATE) 的 failover。
  • 主库异常关闭的处理:按“先判缺口 → 判RPO → 决策 failover/switchover”的流程执行,并对网络/参数与 SRL 做好预防加固。

1) WAIT_FOR_LOG 的常见根因(含你这次现场)

  1. 主库暂未产生下一序列(业务安静/在线日志未切换)。
  2. 主库被立刻关闭,备库应用到 S-68 后没有 S-69可用,于是进入 WAIT_FOR_LOG。
  3. 传输短暂中断:网络抖动、监听/服务名异常、LOG_ARCHIVE_DEST_n 错误、REOPEN/NET_TIMEOUT 不当。
  4. 只启用“归档应用”而非“实时应用”(SRL 缺失或未在用),导致必须等到归档文件才继续。
  5. FRA/归档空间问题(主库归档受阻、备库接收受阻)。

WAIT_FOR_GAP 不同:WAIT_FOR_LOG 是“等下一段”,而 GAP 是“中间断层”。


2) WAIT_FOR_LOG 场景下能否 failover?

可以的情形

  • 零或可忽略丢失(推荐)
    满足全部或大部分:

    • v$archive_gap 为空
    • 最近接收序列 = 最近已应用序列
    • apply lag≈0;
    • 使用 SRL + Real-Time Apply
    • 传输为 SYNC AFFIRM(可实现 WITH NO DATA LOSS)。
      可执行:
    • Broker:FAILOVER TO <standby> WITH NO DATA LOSS
    • 手工:RECOVER MANAGED STANDBY DATABASE FINISH;ACTIVATE STANDBY DATABASE;
  • 业务允许极小 RPO(有损)
    无缺口但无法证明主库不会再产生日志,或传输恢复无望:

    • Broker:FAILOVER TO <standby> IMMEDIATE
    • 手工:取消恢复 → ACTIVATE STANDBY DATABASE;

    可能丢主库最后尚未送达的一点 redo。

不建议的情形

  • 出现/怀疑 GAPWAIT_FOR_GAPv$archive_gap 非空、RFS/传输报错)。
  • apply lag 明显、接收与应用差距大。
    → 先补齐并应用,再切换。

快速判定 SQL(备库)

-- 1) 是否有缺口
SELECT * FROM v$archive_gap;

-- 2) 进程与序列
SELECT process,status,thread#,sequence#,block#,blocks
FROM   v$managed_standby ORDER BY process;

-- 3) 最近接收/已应用到哪
SELECT thread#, MAX(CASE WHEN archived='YES' THEN sequence# END) last_received
FROM   v$archived_log GROUP BY thread#;

SELECT thread#, MAX(CASE WHEN applied='YES' THEN sequence# END) last_applied
FROM   v$archived_log GROUP BY thread#;

-- 4) 延迟
SELECT name,value FROM v$dataguard_stats
WHERE name IN ('transport lag','apply lag');

3) 主库异常关闭的标准处置流程(建议落到SOP)

A. 现场初判(1–3 分钟)

  1. 业务侧沟通:确认 RPO/RTO 目标(是否必须 0 丢失)。

  2. 备库检查(上面四组 SQL):

    • no gap + apply≈received → 可按 RPO 决策切换;
    • 若有 gap/报错 → 先补日志或判断主库可否短时拉起生成/抽取日志。

B. 决策分支

  • 目标 RPO=0(零丢失)
    必须满足:SYNC AFFIRM + SRL + 实时应用 + 无缺口

    • Broker:FAILOVER ... WITH NO DATA LOSS
    • 手工:FINISHACTIVATE
      若条件不满足且业务仍要求 0 丢失 → 不可切换,应尝试拉起主库导出/注册缺失 redo(含在线日志)。
  • 接受 RPO>0(有损)

    • Broker:FAILOVER ... IMMEDIATE
    • 手工:CANCELACTIVATE
      之后按 C 节把旧主库收编为新备库。

C. 切换后的收敛(主库恢复/回补)

  • 开启 Flashback 的理想路径
    旧主库恢复后 → FLASHBACK DATABASE TO SCN <新主库切换点> → 转换为备库并加入 Data Guard。
  • 无 Flashback
    RMAN DUPLICATE FROM ACTIVE 重建为备库。

4) 事前加固(强烈建议)

  1. SRL 充足且在用
  • 每线程 组数 ≥ 在线日志组数,大小匹配;

  • 备库启用实时应用:

    ALTER DATABASE RECOVER MANAGED STANDBY DATABASE
      USING CURRENT LOGFILE DISCONNECT;
    
  1. 传输参数(主库 LOG_ARCHIVE_DEST_n)
  • 如果追求 0 丢失:SYNC AFFIRM NET_TIMEOUT=30 REOPEN=60 VALID_FOR=(ONLINE_LOGFILE,PRIMARY_ROLE)
  • 否则:ASYNC NOAFFIRM + 合理 NET_TIMEOUT/REOPEN
  • 定期 ARCHIVE LOG CURRENT 验证通道;监控 v$archive_dest_status.error
  1. 网络与 OS
  • TCP keepalive(示例):

    net.ipv4.tcp_keepalive_time=60
    net.ipv4.tcp_keepalive_intvl=10
    net.ipv4.tcp_keepalive_probes=6
    
  • MTU/丢包/会话老化策略检查,备库监听与服务名一致可达。

  1. 容量与告警
  • FRA 容量≥峰值两倍,监控 ORA-198xx;
  • 清理/压缩归档(必要时启 LOG_ARCHIVE_DEST_n ... COMPRESSION=ENABLE)。
  1. 补丁一致性
  • 定期跑 datapatch -verbose,清理你看到的 DBMS_BACKUP_RESTORE/DBMS_RCVMAN 版本不一致告警,避免 RMAN 任务异常。

5) 给你们 HA 前置校验的落地建议(伪代码)

if status == WAIT_FOR_GAP or v$archive_gap non-empty:
    block_failover("GAP present")
elif status in (WAIT_FOR_LOG, APPLYING_LOG):
    if last_received_seq == last_applied_seq and apply_lag≈0:
        allow_failover(mode = NO_DATA_LOSS if SYNC+SRL else POLICY)
    else:
        allow_failover_only_if(RPO>0 explicitly accepted)
else:
    block_or_require_manual_review()

小结

  • 根因:WAIT_FOR_LOG 说明“缺下一段”,在你这次是主库被 shutdown immediate 后不再产生日志导致。
  • 是否可切:可,在 无缺口 且满足你的 RPO 前提下实施(满足 SYNC+SRL 时可 0 丢失;否则有损)。
  • 以后怎么做:按 SOP 快速判定 → 按 RPO 决策 → 切换后收敛;同时从 SRL/传输参数/网络/FRA/补丁 五方面做预防加固。

最近接收序列 = 最近已应用序列; 这个是什么,要怎么判断

好问题!这两个“序列”都是指 主库 redo 日志的 sequence#,在备库侧各自代表:

  • 最近接收序列(last_received_seq):备库已经收到并登记的最新一段归档日志(或由 RFS/FAL拉取)的最大 sequence#
  • 最近已应用序列(last_applied_seq):备库已经应用完成(Apply=YES)的最大 sequence#

last_received_seq = last_applied_seq 且无 GAP 时,说明“收到了多少就应用到多少”,MRP0 进入 WAIT_FOR_LOG 纯属“等下一段”,这时按你的 RPO 策略可考虑切换。


一把梭的判定 SQL(在备库执行)

-- 1) 是否存在缺口(有值就先别切)
SELECT * FROM v$archive_gap;

-- 2) 最近接收 vs 最近已应用(多线程环境逐线程看)
WITH r AS (
  SELECT thread#, MAX(sequence#) AS last_received_seq
  FROM   v$archived_log
  WHERE  registrar IN ('RFS','FAL')  -- 备库收到的归档
  GROUP BY thread#
),
a AS (
  SELECT thread#, MAX(sequence#) AS last_applied_seq
  FROM   v$archived_log
  WHERE  applied = 'YES'             -- 备库已完整应用的归档
  GROUP BY thread#
)
SELECT COALESCE(r.thread#, a.thread#) AS thread#,
       r.last_received_seq,
       a.last_applied_seq,
       (r.last_received_seq - a.last_applied_seq) AS seq_gap
FROM   r FULL OUTER JOIN a USING(thread#)
ORDER  BY 1;

解读:

  • seq_gap = 0v$archive_gap 为空 ⇒ “收多少用多少”
  • seq_gap > 0 ⇒ 还在追日志或卡住,先别切。

再配合进程与延迟快速看一眼:

-- 3) MRP0/RFS状态与当前正在应用的序列(实时把关)
SELECT process, status, thread#, sequence#, block#, blocks
FROM   v$managed_standby
WHERE  process IN ('MRP0','RFS')
ORDER  BY process;

-- 4) 传输/应用延迟(近似判断是否贴近实时)
SELECT name, value
FROM   v$dataguard_stats
WHERE  name IN ('transport lag','apply lag','apply finish time');

备注(实时应用场景):如果启用了 Standby Redo Log + USING CURRENT LOGFILE,MRP0 可能在应用 SRL 中的当前序列,这时 last_applied_seq 只统计已完整应用的归档,看起来会落后 1;结合 v$managed_standbyMRP0 status=APPLYING_LOG / WAIT_FOR_LOGapply lag≈0 才能判断是否“基本追平”。


小结(如何用它决定能否切)

  1. 先看 v$archive_gap:有缺口就补,没缺口再往下。
  2. 看上面的对比查询:所有线程 seq_gap=0 ⇒ “收多少用多少”。
  3. v$managed_standby + v$dataguard_statsWAIT_FOR_LOGAPPLYING_LOGapply lag≈0 ⇒ 在你接受的 RPO 下即可切换;若要求 RPO=0,需再满足 SYNC+SRL 等条件。

预警日志的内容可以作证吗?

这三行正好能证明当时“最近接收序列 = 最近已应用序列 = 68”,属于纯粹在“等下一段(69)”的 WAIT_FOR_LOG 场景。

怎么从日志看出来:

  • 14:00:15 Recovery of Online Redo Log ... Seq 68 → 备库正在应用 Seq 68(实时应用 SRL/在线日志)。
  • 14:07:47 ARC1 ... Archived Log entry ... S-68 → 备库已把 Seq 68 完整归档到本地(说明已完整接收已应用完该序列)。
  • 紧接着(你之前贴过)PR00: Media Recovery Waiting for T-1.S-69 → 应用完 68,开始等 69

=> 因此在 14:07:47 时刻:
last_received_seq = 68(已归档到本地)
last_applied_seq = 68(应用完并等待 69)

对切换的含义:

  • 若主库已关机、不再产生 69,且确认无 GAP,这是可在 WAIT_FOR_LOG 下切换的典型“收多少用多少”状态。
  • 需做到零丢失时,还要满足 SYNC + SRL 实时应用 等前提;否则按策略接受极小 RPO(IMMEDIATE)即可。

严谨起见,可在备库再跑一遍校验:

SELECT * FROM v$archive_gap;  -- 应为空
WITH r AS (
  SELECT thread#, MAX(sequence#) last_received_seq
  FROM v$archived_log WHERE registrar IN ('RFS','FAL') GROUP BY thread#
),
a AS (
  SELECT thread#, MAX(sequence#) last_applied_seq
  FROM v$archived_log WHERE applied='YES' GROUP BY thread#
)
SELECT COALESCE(r.thread#,a.thread#) thread#, r.last_received_seq, a.last_applied_seq
FROM r FULL OUTER JOIN a USING(thread#);

看到线程1里两个值同为 68(且无 GAP),就与这段日志结论一致,可以据此决定是否发起 failover。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值