Oracle DataGuard 日志传输——LGWR SYNC/ASYNC、AFFIRM/NOAFFIRM 与网络延迟博弈

DataGuard 是 Oracle 高可用的基石,但日志传输这块的水很深。很多 DBA 配 DG 时,保护模式选 MAXIMUM PERFORMANCE,传输模式选 ARCH,以为这样"性能最好",结果主库崩溃时丢了几小时数据,业务总监指着鼻子骂:"我要这灾备有何用?"反过来,有人选 MAXIMUM AVAILABILITY + LGWR SYNC,结果主库每次 COMMIT 都要等备库确认,Log File Sync 从 2ms 变成 50ms,交易接口全超时。这篇文章把 LGWR/ARCH、SYNC/ASYNC、AFFIRM/NOAFFIRM 的组合效应拆清楚,再给一个我们花了两周才调好的真实案例。

1 日志传输不是单选题,是四参数的组合题

DataGuard 的日志传输涉及四个关键参数:第一,传输进程:LGWR(实时传输)vs ARCH(归档后传输)。LGWR 模式下,主库的 LGWR 进程每生成一段 redo,就通过 LNS(Log Writer Network Server)进程实时发送到备库;ARCH 模式下,LGWR 只写本地在线日志,等日志切换后由 ARCn 进程把归档文件拷贝到备库。LGWR 的延迟低(毫秒级),但占用网络带宽和主库 CPU;ARCH 的延迟高(分钟级),但主库开销小。

第二,同步模式:SYNC(同步)vs ASYNC(异步)。SYNC 模式下,主库 LGWR 必须收到备库的写盘确认(ACK)后,才认为事务提交成功;ASYNC 模式下,LGWR 把 redo 发到网络缓冲区就返回,不等备库确认。SYNC 保证零数据丢失(RPO=0),但 COMMIT 延迟大;ASYNC 延迟小,但主库崩溃时可能丢失最后几秒的 redo。第三,确认模式:AFFIRM(确认写盘)vs NOAFFIRM(不确认)。AFFIRM 要求备库把 redo 写到本地磁盘后才发 ACK;NOAFFIRM 只要求备库收到 redo 到内存就发 ACK。AFFIRM 更安全,但延迟更大;NOAFFIRM 更快,但备库崩溃时可能丢失内存中的 redo。第四,保护模式:MAXIMUM PROTECTION(最大保护)、MAXIMUM AVAILABILITY(最高可用)、MAXIMUM PERFORMANCE(最高性能)。保护模式是前三参数的组合封装:MAXIMUM PROTECTION = LGWR + SYNC + AFFIRM,备库不可用则主库挂起,确保绝对零丢失;MAXIMUM AVAILABILITY = LGWR + SYNC + AFFIRM,但备库不可用时自动降级为 ASYNC,不挂主库;MAXIMUM PERFORMANCE = LGWR/ARCH + ASYNC + NOAFFIRM,主库性能优先,丢数据风险最大。

2 网络延迟:决定 SYNC 模式生死的关键

SYNC 模式的核心瓶颈是网络 RTT(Round Trip Time)。主库发 redo → 备库写盘 → 备库发 ACK,这个过程至少需要一个 RTT。同城双中心,RTT 通常 1-5ms,SYNC 的额外开销可以忽略;异地容灾,RTT 50-200ms,SYNC 会让 Log File Sync 暴涨,OLTP 系统基本不可用。我们给一个跨省容灾的客户做 DG,北京主库 + 广州备库,RTT 约 80ms。一开始选 MAXIMUM AVAILABILITY(SYNC),结果订单提交的 Log File Sync 从 3ms 涨到 85ms,TPS 从 5000 降到 1800,用户支付时频繁超时。后来改成 ASYNC + FASTSYNC(12c 特性,内存级确认),Log File Sync 回到 5ms,TPS 恢复到 4800。代价是 RPO 从 0 变成约 2 秒(主库崩溃时最多丢 2 秒 redo),业务方接受了这个 trade-off。这个案例说明:异地容灾别硬上 SYNC,网络延迟是物理定律,Oracle 也突破不了。

除了 RTT,网络带宽也是瓶颈。LGWR ASYNC 模式下,主库redo 产生速率可能达到 500MB/s,如果网络带宽只有 1Gb/s(125MB/s),网络缓冲区会迅速填满,LNS 进程阻塞,主库 LGWR 间接阻塞,最后效果跟 SYNC 差不多——主库等网络。所以 ASYNC 不一定是最佳的,它需要足够的网络带宽。我们的经验公式:网络带宽 ≥ 峰值 redo 速率 × 2。比如峰值 redo 100MB/s,带宽至少 200MB/s(1.6Gb/s),留一倍余量应对突发。如果带宽不够,要么压缩传输(REDO_TRANSPORT_COMPRESSION = ENABLE),要么用 ARCH 模式(批量传归档,带宽利用率更高)。

3 实验:四种传输模式的延迟与吞吐量对比

实验环境:主库和备库都是 Oracle 19c,单实例,通过 1GbE 以太网连接(RTT 模拟 2ms/50ms 两档)。测试方法:Swingbench OLTP,100 并发,每事务 5 条 DML + 1 条 COMMIT。对比四种配置:A: LGWR SYNC AFFIRM(MAXIMUM AVAILABILITY)B: LGWR SYNC NOAFFIRM(折中方案)C: LGWR ASYNC NOAFFIRM(MAXIMUM PERFORMANCE)D: ARCH ASYNC NOAFFIRM(传统方案)

-- 配置 A:LGWR SYNC AFFIRM
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2 =
'SERVICE=stdby LGWR SYNC AFFIRM VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stdby';
ALTER SYSTEM SET LOG_ARCHIVE_CONFIG='DG_CONFIG=(prod,stdby)';

-- 配置 C:LGWR ASYNC NOAFFIRM
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2 =
'SERVICE=stdby LGWR ASYNC NOAFFIRM VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=stdby';

-- 监控日志传输延迟
SELECT dest_name, transmission_mode, synchronism, affirm,
       round((sysdate - last_sequence#_sent_time)*86400,2) lag_seconds
FROM   v$archive_dest_status WHERE dest_id = 2;

-- 监控主库 Log File Sync
SELECT event, avg_wait_time_micro/1000 avg_ms, max_wait_time_micro/1000 max_ms
FROM   v$system_event WHERE event = 'log file sync';

-- 监控备库应用延迟
SELECT name, value/1000 lag_ms
FROM   v$dataguard_stats WHERE name = 'apply lag';

实验结果(RTT=2ms,同城):配置 A:Log File Sync avg=4.5ms,TPS=4800,备库 lag=0ms(实时),RPO=0。配置 B:Log File Sync avg=3.8ms,TPS=4950,备库 lag=0ms,RPO≈0(NOAFFIRM 极小风险)。配置 C:Log File Sync avg=2.5ms,TPS=5200,备库 lag=200ms,RPO≈200ms。配置 D:Log File Sync avg=2.2ms,TPS=5300,备库 lag=45 秒,RPO≈45 秒。实验结果(RTT=50ms,异地):配置 A:Log File Sync avg=52ms,TPS=2100,备库 lag=0ms,RPO=0。配置 B:Log File Sync avg=28ms,TPS=3800,备库 lag=0ms,RPO≈0。配置 C:Log File Sync avg=4.5ms,TPS=4700,备库 lag=800ms,RPO≈800ms。配置 D:Log File Sync avg=3.5ms,TPS=4900,备库 lag=120 秒,RPO≈120 秒。

从数据可以看出:同城场景,配置 B(LGWR SYNC NOAFFIRM)是甜点区——几乎零丢失,性能损失 <5%,比 AFFIRM 快 20%。异地场景,配置 C(LGWR ASYNC)是甜点区——Log File Sync 只比本地多 2ms,RPO 约 1 秒,可接受。配置 A 在异地是自杀式选择,TPS 掉 60%,业务无法容忍。配置 D 虽然主库性能最好,但备库 lag 120 秒,对于要求 RPO < 30 秒的业务,完全不合格。所以选型不是"选最好的",是"选最合适的"。

【踩坑笔记】12c 以后有个折中特性叫 FASTSYNC:LGWR SYNC NOAFFIRM 的封装,但备库的写盘由后台进程异步完成,主库只等备库内存确认。实际效果接近 SYNC NOAFFIRM,但 Oracle 官方推荐用 FASTSYNC 替代手动配 SYNC NOAFFIRM。另外,网络压缩(REDO_TRANSPORT_COMPRESSION)在带宽紧张时很有用,但会消耗 5-10% 的 CPU,需要在主库 CPU 和带宽之间权衡。

4 日志 Gap 的排查:不是网络断了,是备库应用慢了

很多 DBA 看到备库 lag 高,第一反应是"网络断了,传不过去"。实际上,大部分 lag 不是传输问题,是备库应用问题。DataGuard 的 lag 分两种:Transport Lag:redo 从主库到备库的传输延迟。如果主库 redo 产生 500MB/s,网络带宽 1Gb/s,传输 lag 会累积。Apply Lag:备库收到 redo 后,MRP(Managed Recovery Process)应用到数据文件的延迟。如果备库的 I/O 慢(比如备库是 SATA 盘,主库是 SSD),或者备库在跑只读查询(ADG),查询占用了 I/O 带宽,MRP 应用 redo 就会变慢,Apply Lag 增加。

我们排查 lag 的标准流程:第一步,查 V$ARCHIVE_DEST_STATUS 的 TRANSMIT_MODE 和 GAP_STATUS,确认是否有归档 GAP。如果有 GAP,说明传输断了或归档文件丢了,需要补传。第二步,查 V$DATAGUARD_STATS 的 apply lag 和 transport lag,看哪个更大。如果 transport lag 小(<1 秒)但 apply lag 大(>10 秒),说明网络没问题,备库应用慢。第三步,查备库的 V$SYSTEM_EVENT,看 MRP 的等待事件。如果 MRP 主要在等 'log file parallel write',说明备库写盘慢;如果等 'CPU + Wait for CPU',说明备库 CPU 不够;如果等 'read by other session',说明备库的只读查询在抢 I/O。我们给一个客户排查时,发现备库 Apply Lag 30 秒,但 Transport Lag 只有 0.5 秒。进一步查,发现备库在跑 8 个并行报表,占满了 I/O 带宽,MRP 写数据文件时抢不过报表查询。解决办法:给 MRP 设 I/O 优先级(ionice),或者限制报表的并行度(DOP 从 8 降到 2),Apply Lag 降到 2 秒。这个案例说明:DG 调优不只是主库的事,备库的负载管理同样重要。

5 总结:DG 日志传输的选型矩阵

经过多个客户现场的验证,我们总结了一个选型矩阵:同城双活(RTT < 5ms):LGWR SYNC NOAFFIRM(FASTSYNC),保护模式 MAXIMUM AVAILABILITY,RPO≈0,性能损失 <5%。同城灾备(RTT 5-20ms):LGWR ASYNC AFFIRM,保护模式 MAXIMUM PERFORMANCE,RPO < 1 秒,性能损失 <3%。异地容灾(RTT 20-100ms):LGWR ASYNC NOAFFIRM + 压缩,保护模式 MAXIMUM PERFORMANCE,RPO 1-5 秒,性能损失 <5%。跨国容灾(RTT > 100ms):ARCH ASYNC + 压缩,或者改用 Oracle GoldenGate(逻辑复制,带宽需求低),DG 的物理复制在这种延迟下基本不可用。最后送一句话:DG 不是配完就忘的,网络抖动、存储老化、备库负载变化,都会影响传输效率。建议每天早会看一眼 V$DATAGUARD_STATS,lag 超过阈值立即排查,别等主库崩了才发现备库落后 2 小时。


请使用浏览器的分享功能分享到微信等