Ping延迟低但DG传输卡顿,因ping仅测ICMP小包往返,无法反映TCP吞吐瓶颈;DG依赖Oracle专有协议栈,受TCP窗口、丢包率、RTT等影响,需调优tcp_rmem/wmem、启用SACK与timestamp、校准MTU及禁用TFO。
为什么 ping 延迟低但 DG 传输卡顿?
因为 ping 测的是 icmp 小包往返,不反映 tcp 数据流的真实瓶颈。dg(dataguard)走的是 oracle 的专有网络协议栈,底层依赖 tcp 连接质量,而 tcp 吞吐量直接受窗口大小、丢包率、rtt 影响——ping 看不到这些。
常见错误现象:ping 显示 1ms,但 DG 日志反复出现 ORA-16198: timeout received during network communication,或 ARCH 归档日志传输延迟飙升。
- 检查实际 TCP 往返时延:用
tcpping -x 5 <host> 1521</host>替代ping,它测的是目标端口的 TCP SYN 响应时间 - 确认是否启用了 TCP timestamp 和 window scaling:Linux 下运行
sysctl net.ipv4.tcp_timestamps和net.ipv4.tcp_window_scaling,两者都必须为1 - 避免在中间设备(如防火墙、负载均衡器)上截断 TCP options,否则窗口缩放失效,最大接收窗口被锁死在
64KB
tcp_rmem 和 tcp_wmem 怎么设才不拖慢 DG?
DG 主库发送归档日志、备库拉取日志,都是长连接、高吞吐场景。系统默认的 TCP 缓冲区太小(如 Linux 默认 tcp_rmem = "4096 131072 6291456"),会导致频繁等待 ACK、窗口通告不足,尤其在高延迟链路上更明显。
关键不是“调大”,而是匹配带宽时延积(BDP):估算公式是 带宽(B/s) × RTT(s)。例如 100Mbps 链路 + 20ms RTT → BDP ≈ 250KB,那么 tcp_rmem 的上限至少设为 524288(512KB)。
- 临时生效:
sysctl -w net.ipv4.tcp_rmem="4096 262144 524288"和net.ipv4.tcp_wmem="4096 262144 524288" - 永久生效:写入
/etc/sysctl.conf,注意第三项(max)必须 ≥ 第二项(default),否则内核会静默忽略 - Oracle 12c 及以后建议同步调整
_tcp_fast_open隐含参数为FALSE(默认为TRUE),某些内核版本下 TFO 与 DG 的重传逻辑存在兼容问题
DG 专用网络要不要开 net.ipv4.tcp_sack?
要开,且必须开。SACK(Selective Acknowledgment)让接收方能告诉发送方“只丢了第3段,其余都收到了”,避免整个窗口重传。DG 场景下,哪怕单个归档日志块(通常 1MB+)在网络中某处丢一个 TCP segment,没 SACK 就得重发整块,极大拖慢传输效率。
错误配置表现:v$dataguard_stats 中 transport lag 持续增长,v$managed_standby 显示 MRP0 进程 CPU 占用低但应用延迟高,说明不是备库处理慢,而是主库发不出去。
- 确认状态:
sysctl net.ipv4.tcp_sack输出必须是1 - 禁用 SACK 的典型场景是老旧安全设备强制 strip TCP options,此时应更换设备策略,而非妥协关闭 SACK
- 不要混淆
tcp_sack和tcp_dsack(后者是检测重复包,对 DG 无直接帮助,可关)
Oracle 网络参数和 OS TCP 参数谁优先级更高?
OS TCP 参数是底层基础,Oracle 网络参数(如 SQLNET.SEND_TIMEOUT、SQLNET.RECV_TIMEOUT)只是上层超时控制,不改变 TCP 行为本身。如果 OS 层窗口太小、SACK 关闭、缓冲区溢出,再怎么调 Oracle 超时也没用——连接根本建立不稳或发不出数据。
最容易被忽略的一点:DG 使用的是 Oracle Net 的专用连接(非普通 SQL*Net),其行为受 listener.ora 中 SDU(Session Data Unit)和 TDU(Transport Data Unit)影响,但这两个值不能超过 OS 的 MSS(Maximum Segment Size),而 MSS 又由路径 MTU 决定。MTU 不匹配会导致分片,而分片在跨公网或某些云网络中极易丢弃。
- 查当前路径 MTU:
tracepath <standby_ip></standby_ip>或ip route get <standby_ip></standby_ip> - 若路径 MTU 是
1400,则SDU最大建议设为8192(Oracle 默认),但需确保tcp_rmem上限 ≥SDU × 4,否则缓冲区撑不住突发流量 - 别迷信“调大所有超时参数”,
SQLNET.SEND_TIMEOUT=0(禁用)可能让 DG 在网络抖动时无限挂起,反而更糟









