尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Oracle Data Guard standby redo log配置与WAIT_FOR_LOG状态实战解析

Oracle Data Guard standby redo log配置与WAIT_FOR_LOG状态实战解析 做数据库的人尤其是管过 Oracle Data Guard 的应该都见过这个画面打开 V$STANDBY_LOG一堆 standby redo log 的 STATUS 是 WAIT_FOR_LOG群里立刻就有人开始紧张说备库是不是坏了。更常见的是另一种场景ADG 同步延迟告警主库 log file sync 等待暴涨备库端显示 gap业务方追着问数据到底丢没丢。说实话我见过不止一位同行在这种时候直接重启备库实例结果同步不但没恢复反而把原本健康的 redo 接收链路彻底打断。这篇文章想认真把几件事讲清楚WAIT_FOR_LOG 到底是不是故障standby redo log 的正确配置原则是什么为什么 SRL 配不好主库提交性能会被拖死以及 ADG 显示 gap 之后该怎么系统化处置。内容偏实战适合刚接手 Data Guard 的 DBA也适合已经把 sync 模式跑起来、但一直没把 SRL 细节琢磨透的同行。1. WAIT_FOR_LOG 状态先分清是健康还是故障1.1 一个真实出现的同步延迟场景先说一个我处理过的案例。某在线交易系统主备库跑的是 Maximum Availability 模式平时 log file sync 平均等待在 3ms 左右。某天晚高峰应用开始大面积超时AWR 里 log file sync 飙到 40ms 以上但数据库负载、SQL 执行计划都没有明显变化。我第一反应是网络问题结果 ping 主备两端延迟不到 1ms网络层面干干净净。再查主库的 Data Guard 传输目标状态发现 V$ARCHIVE_DEST_STATUS 里 GAP_STATUS 已经出现 GAPV$MANAGED_STANDBY 里的 RFS 进程停在某个 sequence 号上不再前进。回头看备库的 V$STANDBY_LOG好几个 SRL 组要么 ACTIVE 卡住要么停在 WAIT_FOR_LOG 空等。最后定位下来根因一点都不玄乎SRL 组数不够备库 ARCn 归档速度跟不上 RFS 接收速度主库 LGWR 每笔提交都在等备库确认整个业务被拖住。这个案例很有代表性因为它说明一个容易被忽略的事实很多同步问题表面在网络、在负载实际上根子在备库的 SRL 配置上。1.2 V$STANDBY_LOG 各状态分别代表什么要判断 WAIT_FOR_LOG 是不是问题先得知道 V$STANDBY_LOG 里各个状态的含义。这张表建议收藏STATUS含义是否异常UNASSIGNEDSRL 尚未分配给任何线程一般正常ACTIVESRL 正在接收 redo或刚接收完还没归档正常WAIT_FOR_LOGSRL 当前为空等待主库发送下一个 redo 日志空闲时正常有 redo 却不来才异常CLEARINGSRL 正在被清理重置准备复用短暂存在正常CLEARING_CURRENTSRL 正在清理且可能是当前正在使用的日志短暂存在正常注意一个细节这几个状态里真正危险的往往不是 WAIT_FOR_LOG 本身而是某个 SRL 在长时期没有任何状态变化同时两端 sequence 号差距持续拉大。1.3 WAIT_FOR_LOG 的两种截然不同解读第一种健康状态。备库已经追平主库当前没有新的 redo 日志到达空着的 SRL 自然会显示 WAIT_FOR_LOG。这就像电梯空着在等下一批乘客完全正常。你不可能也不应该追求所有 SRL 永远不出现 WAIT_FOR_LOG只要备库有富余的 SRL就总会有日志组处于这个状态。第二种故障状态。主库已经切换了好几个 redo 日志sequence 号一直在涨备库 SRL 却始终停在 WAIT_FOR_LOG或者某个 ACTIVE 的 SRL 不再推进V$ARCHIVE_GAP 开始产生记录。这种情况说明 redo 没有按预期到达备库要么网络有问题要么 RFS 进程异常要么 SRL 都占满了没有空组可接收。所以判断的核心不是盯着单个 SRL 的状态而是看主备两端的 sequence 是否同步、transport lag 是否持续增长。我见过太多人对着 WAIT_FOR_LOG 瞎紧张其实正确的操作是立刻去查 V$ARCHIVE_DEST_STATUS 的 GAP_STATUS 和 V$DATAGUARD_STATS 的 transport lag用这两个指标判断同步是否真的出了问题。2. standby redo log 的运作机制以及它卡住时主库会发生什么2.1 redo 从主库到备库的完整链路要理解 SRL 配置为什么重要得先看懂 redo 在 Data Guard 里是怎么流动的。主库的 LGWR 进程写本地 online redo log同时通过网络把 redo 数据发给备库的 RFS 进程。RFS 收到数据后不是直接写归档文件而是先写入 SRL。SRL 写满之后备库的 ARCn 进程会把 SRL 的内容归档成 archived log。在 ADG 场景下MRP 进程既可以等归档完成后应用也可以在实时应用模式USING CURRENT LOGFILE下直接读取 SRL 去做 apply。这条链路里SRL 是 redo 到达备库后的第一个落点也是整个备库接收侧的缓冲。它的容量、组数、磁盘性能直接决定了备库能多快接收、多快确认、多快归档。任何一个环节堵住影响的不只是备库而是通过同步机制反向传导到主库。2.2 LGWR SYNC 确认机制备库写慢主库就提交慢Maximum Availability 模式的核心机制是主库 LGWR 把 redo 同步发送给备库 RFSRFS 完整写入 SRL 并落盘之后返回确认给主库 LGWR。主库 LGWR 只有收到这个确认才认为这一笔提交完成。这个设计保证了 RPO0数据零丢失但代价非常直接备库磁盘每次写 SRL 的耗时会原封不动地叠加到主库每一笔事务提交的路径上。也就是说主库提交延迟 网络 RTT 备库写 SRL 耗时。网络延迟 1ms备库磁盘写 10ms那一笔提交就得等 11ms。理解了这一点就明白为什么 SRL 放错了磁盘、组数不够、FRA 空间紧张都会直接拖垮主库业务而不是只影响备库。2.3 SRL 配置不当导致等待的三种典型情况第一种SRL 比主库 online redo 小。主库 redo 日志是 2G备库 SRL 只配了 1G。主库一个 log switch 产生的 redo 量超过 SRL 容量RFS 写到一半写不下只能卡住等待主库 LGWR 迟迟收不到确认提交全部排队。这种问题在业务低峰期不明显一到高峰期 redo 生成量大立刻爆雷。第二种SRL 组数不足。备库所有的 SRL 都处于 ACTIVE 或 CLEARING 状态ARCn 归档速度跟不上没有空组释放出来。RFS 想接收新的 redo却找不到可写的 SRL只能干等。这就像快递站只有两个卸货口一个在卸货一个在分拣第三辆卡车到了只能排队。第三种RAC 环境下漏配线程。主库是两个实例的双线程架构备库 SRL 却只配了 thread 1thread 2 的 redo 到了备库没有接收位置。这类问题最隐蔽因为在单实例巡检时怎么看都正常一旦跨线程切换流量gap 就开始出现。这三种情况表现各不相同根因说穿了就一句话SRL 的容量和数量配不上主库的 redo 生成节奏。3. 正确配置 standby redo log 的步骤与原则3.1 第一步先摸清主库 redo 的现状配置 SRL 之前先得知道主库的 redo 到底是什么规模。在主库执行这条 SQLSELECT THREAD#, GROUP#, BYTES / 1024 / 1024 AS SIZE_MB, STATUS, ARCHIVED FROM V$LOG ORDER BY THREAD#, GROUP#;重点记录两样东西每个线程有多少组 online redo log最大的一组是多少兆。这两个数字就是后续配置 SRL 的基准。如果主库是 RAC每个实例对应一个 thread必须按线程分别统计不能只拿一个实例的数据当整库的数据。还要顺带看一个指标高峰期 redo 的生成速率。可以用 v$sysstat 里的 redo size 增量除以运行时间估算也可以看 AWR 里的 Redo Generated per Second。这一步很多人忽略但它决定了 SRL 组数是不是需要额外增加余量。3.2 尺寸与组数的两条硬规则配置 SRL 有两条公认的硬规则建议直接焊死在脑子里。规则一SRL 大小必须大于等于主库最大的 online redo log 大小。最稳妥的做法就是完全等大。主库 redo 2GSRL 也配 2G。不要图省事配小一号更不要觉得备库压力小所以可以小一点。这跟压力无关纯粹是容量匹配问题主库的 log switch 一旦产生超过 SRL 容量的 redoRFS 就写不下整个同步链路立刻卡住。规则二每个 thread 的 SRL 组数至少比主库对应 thread 的 online redo 组数多一组。假设主库每个线程有 4 组 online redo log那备库每个线程至少配 5 组 SRL。为什么必须多一组因为主库 redo 日志切换时RFS 刚写完一个 SRL必须立刻有一个空的 SRL 来接下一个 redo。如果所有 SRL 都处于被 ARCn 归档的状态没有任何空组可用RFS 就只能等待归档完成。多一组 SRL就是给归档操作留出时间窗口避免接收端断档。对于重负载的 OLTP 系统我通常会建议在经济允许的情况下按主库组数 2 来配更从容。成本只多两三组日志文件换来的是高峰期归档竞争时不会轻易出现断档。3.3 RAC 环境下的线程覆盖处理单实例环境直接加组就行RAC 环境要特别注意 THREAD 参数。下面这段是双线程 RAC 备库正确添加 SRL 的示例ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 11 (/u01/app/oracle/oradata/STANDBY/srl_11a.log) SIZE 2G; ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 GROUP 21 (/u01/app/oracle/oradata/STANDBY/srl_21a.log) SIZE 2G;如果不指定 THREADOracle 会把日志组自动分配到某个线程。多线程环境下漏配某一线程那个线程的 redo 到达备库时就没有接收位置gap 迟早出现。配完以后一定要用 V$STANDBY_LOG 核对每个线程的覆盖情况SELECT THREAD#, GROUP#, BYTES / 1024 / 1024 AS SIZE_MB, STATUS FROM V$STANDBY_LOG ORDER BY THREAD#, GROUP#;核对的标准很简单每个线程的 SRL 组数都达标大小都达标。提示RAC 备库增加 SRL 时确保所有线程都有对应配置不要指望之后再加。线程覆盖不全会变成隐形的雷平时没事一旦跨实例流量迁移就炸。3.4 在线添加、清理与删除 SRL 的实操命令添加 SRL 的完整语法ALTER DATABASE ADD STANDBY LOGFILE GROUP 12 (/u01/app/oracle/oradata/STANDBY/srl_12a.log) SIZE 2G;想给一组配多个 member 做冗余就写多个路径ALTER DATABASE ADD STANDBY LOGFILE GROUP 12 (/u01/app/oracle/oradata/STANDBY/srl_12a.log, /u02/app/oracle/oradata/STANDBY/srl_12b.log) SIZE 2G;遇到 SRL 状态卡住需要强制清理时用ALTER DATABASE CLEAR LOGFILE GROUP 12;如果该组里有未归档数据但你确认不需要了可以加 UNARCHIVED 强制清理ALTER DATABASE CLEAR LOGFILE UNARCHIVED GROUP 12;删除 SRLALTER DATABASE DROP STANDBY LOGFILE GROUP 12;这里面有几个实操要点都是踩过坑换来的。第一SRL 处于 ACTIVE 状态正在被 RFS 写入时不能直接 drop会报错。要等到它完成接收并切换出去后再操作或者直接选一个空闲的组先动刀。第二修改 SRL 前最好在备库开一个维护窗口因为操作期间 redo 接收可能出现短暂中断。第三改完以后必须在 V$STANDBY_LOG 里复查一次确认组数、大小、线程覆盖都符合预期。4. 拿下 WAIT_FOR_LOG除了配置之外还有哪些性能瓶颈4.1 备库磁盘 IO 与 fsync 对同步延迟的放大很多 DBA 把 SRL 配好了却发现同步延迟还是高。这时候要往下看一层磁盘。SRL 的写入必须真正落到物理磁盘才能返回确认。如果备库用的是机械盘RAID 卡写缓存又没开启回写每次 SRL 落盘消耗 5 到 10ms 太正常了。主库每笔提交都要等这个时间整体吞吐直接被拖低。这里有个地板效应最容易被人忽略网络再好也没用瓶颈在备库磁盘确认。我记得有一次排查一个持续 20ms 提交延迟的问题网络延迟只有 0.3ms最后发现备库 SRL 跟 FRA 放在同一个磁盘组ARCn 归档和 RFS 写入在抢同一块盘的 IO每次确认都排长队。把 SRL 挪到独立的 SSD 磁盘组之后提交延迟立刻回落到 2ms 以内前后对比非常鲜明。给几条实操建议SRL 文件跟控制文件、在线 redo log 分开存放避免互相抢 IO有条件上 SSD或者至少把 SRL 放到独立的物理磁盘组同时检查文件系统的挂载参数确认没有引入额外的 buffer让数据库的写盘行为保持可控。SRL 的路径规划不建议直接丢在 FRA 里图省事FRA 空间压力一大SRL 归档和清理互相打架最终仍然会传导到主库。4.2 SYNC 与 ASYNC 的取舍SRL 配置只是基本功真正决定同步性能上限的是保护模式的选择。三种模式的对比值得反复看保护模式LGWR 传输方式数据风险性能特征Maximum ProtectionSYNC AFFIRMRPO0备库故障时主库直接下线提交延迟最高一般不实际使用Maximum AvailabilitySYNC AFFIRMRPO0备库故障时主库继续运行每次提交等备库确认适合核心交易系统Maximum PerformanceASYNC NOAFFIRM备库故障或断连时可能丢失部分 redo提交不等待性能开销极小选型时先回答一个问题业务对 RPO 的真实要求到底是什么核心支付、订单系统要求零丢失那就接受 Maximum Availability 模式下的同步延迟并在 SRL 和磁盘上做足优化。对只要求秒级恢复的报表、数据分析类系统Maximum Performance 完全够用没必要硬切 sync 模式给自己找麻烦。我见过有些团队为了看起来更保险把不需要 sync 的系统切成 sync结果天天为提交延迟背锅属于典型的选择性错误。4.3 归档空间的隐形竞争还有一个藏在暗处的问题归档空间。备库的 FRA 或者归档目录一旦满了ARCn 无法把写满的 SRL 归档出去RFS 就永远拿不到空 SRL 继续接收整个接收链路停摆。这跟 SRL 组数不足的表现非常像但根因完全不同。处理方式也很明确日常巡检不要只看 V$STANDBY_LOG还要盯 FRA 使用率和归档清理策略。RMAN 配置的删除策略是否正常执行、归档备份是否按时完成这些都在同步链路里扮演着重要角色。换句话说同步性能优化从来不是一个单点问题而是一条链路的整体优化。SRL 配置正确只是把这条链路上最容易出问题的一段修好了。5. 实战处置 ADG 显示 GAP 的完整流程5.1 发现与确认 gap 的范围前面讲了配置和机制现在来处理 ADG 实际显示 gap 的情况。这类问题一旦出现第一步不是急着补日志而是先确认 gap 到底有多大、缺的是哪些 sequence。在备库执行SELECT * FROM V$ARCHIVE_GAP;返回结果里的 THREAD#、LOW_SEQUENCE#、HIGH_SEQUENCE#就是缺失归档的区间。把这个区间记下来再去备库确认同步延迟SELECT NAME, VALUE, TIME_COMPUTED FROM V$DATAGUARD_STATS WHERE NAME IN (transport lag, apply lag);同时到主库查一下传输目标的状态SELECT DEST_ID, DEST_NAME, STATUS, GAP_STATUS, ERROR FROM V$ARCHIVE_DEST_STATUS WHERE DEST_NAME LIKE %STANDBY%;如果 GAP_STATUS 显示 GAP配合 ERROR 列的信息基本能判断问题出在网络、SRL 还是归档传输。这一步做扎实后续处理才有方向不至于瞎补一通。5.2 手工收集归档补 gap确认 gap 区间后处理的前提是缺失的归档文件还在主库磁盘或备份里。如果已经被清理就得从备份恢复那是另一个更麻烦的话题这里先讨论常规情况。第一步在主库查缺的归档文件路径SELECT THREAD#, SEQUENCE#, NAME FROM V$ARCHIVED_LOG WHERE THREAD# 1 AND SEQUENCE# BETWEEN 100 AND 120 AND NAME IS NOT NULL ORDER BY SEQUENCE#;然后把这些归档文件从主库拷贝到备库比如放到备库的某个临时目录再用 REGISTER 命令注册进去ALTER DATABASE REGISTER OR REPLACE LOGFILE /ora_arch/1_100_987654.arc;注册完成后确认 MRP 的状态。如果备库开了实时应用建议先停掉 MRP 再注册避免读到中间状态ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; -- 注册完成后重新启动 ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;启动之后MRP 会接着 apply 补进来的日志同步逐步恢复。5.3 恢复后的验证与预防补完日志不是终点必须做一轮完整的验证。先看 V$ARCHIVE_GAP 是否已经查不到记录再看 V$DATAGUARD_STATS 里 transport lag 和 apply lag 是否回落到接近零。顺手查一下 V$MANAGED_STANDBY确认 RFS 和 MRP 进程都在正常推进sequence 号跟主库同步增长。这里再分享一个我个人的巡检习惯。每次数据库结构变更包括新增 redo log 组、调整 redo 大小、做 switchover、做 failover 演练我都会顺手把 SRL 的配置复核一遍。很多 gap 事故的源头就是某次调整主库 redo 后没有同步检查备库 SRL 是否仍然符合等大、组数足够、线程覆盖完整这三条规则。Data Guard 的同步性能优化其实没有多高深的技术就是把这些基础规则守住把链路里的每个环节都跑顺WAIT_FOR_LOG 就只是个正常的空闲状态而不是一个让你半夜爬起来处理的事故信号。
返回列表