根本原因是TCP层连接不稳定,具体表现为窗口缩放失效、ACK延迟、缓冲区不匹配三者叠加;需用tcpping测TCP握手延时,确保tcp_timestamps与tcp_window_scaling均为1,中间设备未剥离TCP选项,并按BDP对齐tcp_rmem/wmem及Oracle Net的SDU/BUF_SIZE。
oracle dg远程容灾中网络带宽“跑不满”、传输延迟高、transport lag持续增长,根本不是带宽本身不够,而是tcp连接在长rtt下无法把带宽跑满——窗口缩放失效、ack延迟、缓冲区不匹配三者叠加,让lgwr和arch形同虚设。
tcpping 和 sysctl 检查必须前置
别信ping结果。ICMP小包延时低,不代表Oracle Net走的TCP长连接稳定。tcpping -x 5 host 1521才是真实指标:平均>50ms或抖动>15ms,说明TCP握手已不稳定。
-
sysctl net.ipv4.tcp_timestamps和sysctl net.ipv4.tcp_window_scaling输出必须都为1;任一为0,接收窗口锁死在64KB,千兆链路+50ms RTT下BDP≈6.25MB,直接压垮 - 中间设备(防火墙、WAF、云负载均衡)常默认剥离TCP Options字段,导致
SACK和Window Scale静默失效——用tcpdump抓SYN包确认是否含wscale和timestamp选项
tcp_rmem / tcp_wmem 设置不能只看“大”
盲目加大tcp_rmem和tcp_wmem反而引发ACK延迟、窗口收缩,甚至内核静默忽略该设置。
- 关键约束只有两个:
max≥default,且max≥ 实际BDP × 2~3 - 算BDP:假设带宽100Mbps、RTT=80ms → BDP = (100×10⁶ ÷ 8) × 0.08 ≈ 1MB;建议
tcp_rmem设为"4096 262144 8388608"(即8MB) - 临时生效:
sysctl -w net.ipv4.tcp_rmem="4096 262144 8388608",之后必须sysctl net.ipv4.tcp_rmem确认输出一致,否则未生效
Oracle Net 层 SDU 和 BUF_SIZE 必须与OS层对齐
OS层调了TCP缓冲区,Oracle Net层没跟上,等于在管道中间塞了个漏斗。DG传输链路是「Oracle Net → TCP → NIC」,三层缓冲能力必须对齐,否则瓶颈卡在最窄处。
- 避免全局改:
DEFAULT_SDU_SIZE=32767加到$ORACLE_HOME/network/admin/sqlnet.ora会影响所有客户端连接 - 精准控制:在
tnsnames.ora的DG连接描述符里显式加SEND_BUF_SIZE=10485760和RECV_BUF_SIZE=10485760,值需与OS层tcp_rmem/tcp_wmem的max一致 - 主备库都要配,且
tnsnames.ora中HOST必须填对方私网IP,不是localhost或公网IP
日志传输模式与专用链路决定上限
再怎么调参数,也绕不开物理限制。曾经有客户把DG流量和业务流量混在同一个千兆网卡上,高峰期transport lag高达30分钟;换成10G光纤直连后,延迟降到秒级。
- 最大保护模式要求同步写,对网络时延极度敏感,不适合跨城或高抖动链路
- 异地容灾优先选最大性能模式,并确保
log_archive_dest_n中ASYNC明确启用,别依赖默认行为 - 带宽估算要按峰值redo生成速率来——不是业务吞吐量,而是归档日志大小×单位时间生成数量;例如每分钟生成2GB归档,链路带宽至少需200Mbps(留20%余量)
最容易被忽略的是:调完tcp_rmem和tnsnames.ora后,不验证实际socket接收窗口是否真的扩上去了——ss -i看rcv_space值,它得接近你设的max,否则前面全白干。



















