跨网段dg不稳定主因是中间设备干扰tcp连接,非dg配置问题;需用tcpping测1521端口syn响应,调tcp_rmem/wmem匹配bdp,sdu与socket buffer协同优化,并通过v$managed_standby实时定位卡点。

跨网段传输不稳定,核心问题不是DG配置本身,而是底层TCP连接在跨子网路径上受中间设备干扰或缓冲区失配——AWR和V$DATAGUARD_STATS里的transport_lag只是结果,不是原因。
为什么tcpping比ping更准?
ping只发ICMP小包,完全不走Oracle DG实际使用的TCP端口(默认1521)和协议栈;它显示延迟低,不代表LGWR能稳定把redo块发出去。真正要测的是TCP三次握手响应时间。
- 用
tcpping -x 5 <host> 1521</host>替代ping,确认主备间TCP SYN往返是否抖动或超时 - 如果
tcpping丢包率>0.1%或RTT标准差>5ms,说明链路质量已不满足DG长连接要求,必须查防火墙、ACL、NAT设备是否截断TCP options(如SACK、timestamp) - 特别注意云环境中的安全组/网络ACL:它们常默认放行ICMP但限制TCP连接数或会话老化时间,导致RFS进程反复重建连接
tcp_rmem/tcp_wmem怎么设才不白调?
Linux默认tcp_rmem="4096 131072 6291456"对DG是灾难性的——最大接收窗口6MB看似够大,但内核实际按BDP(带宽×RTT)动态缩放,而DG长连接需要稳定撑满窗口。设错反而触发频繁窗口通告和零窗口探测。
- 先估算BDP:比如主备间带宽100Mbps、RTT=30ms → BDP ≈ 375KB →
tcp_rmem第三项至少设为4194304(4MB),第二项(default)不能低于BDP的1.5倍 - 临时生效:
sysctl -w net.ipv4.tcp_rmem="4096 524288 4194304",同时配net.ipv4.tcp_wmem保持对称 - 必须验证:
ss -i连上DG连接后看cwnd和rcv_space是否稳定在设定值附近;若rcv_space长期<设定max,说明中间设备截断了window scaling选项
Oracle Net层SDU和socket buffer要不要一起调?
SDU(Session Data Unit)是Oracle Net打包redo的逻辑单元,默认8KB(11g+)或2KB(10g),但它不等于TCP MSS。盲目调大SDU会导致单个TCP segment超MTU,触发分片或丢包;只调OS TCP buffer而不调SDU,则Oracle层仍按小包发,无法压满带宽。
- SDU设为
32767前,先用tcpdump抓包确认路径MTU:主备间ping -M do -s 1472 <standby_ip></standby_ip>(1500减去IP/TCP头),若不通则降为1400 - 在
sqlnet.ora中统一设DEFAULT_SDU_SIZE=32767,并在tnsnames.ora的standby连接描述符里显式加(SDU=32767),避免监听器注册时忽略 - Oracle Net socket buffer(
SEND_BUF_SIZE/RECV_BUF_SIZE)建议设为SDU的4–8倍,例如SDU=32KB → buffer设128KB,且必须≤OS层tcp_rmem第二项
V$MANAGED_STANDBY里哪些状态代表真卡顿?
别信transport_lag数值,它每60秒心跳更新一次,在跨网段抖动时严重滞后。真正实时的卡点全在内存视图里,且必须主备库都查。
- 主库查
V$MANAGED_STANDBY:重点关注PROCESS='LGWR'的STATUS是否为ACTIVE、SEQ#是否持续追平V$LOG_HISTORY最新序列;若STATUS是WAIT_FOR_LOG或SEQ#停滞,说明LGWR发不出去,不是网络慢,是本地日志切换或归档路径IO卡住 - 备库查
V$MANAGED_STANDBY:若PROCESS='RFS'的STATUS长期为IDLE或CONNECTED(非WRITING),说明RFS收不到数据,此时立刻检查tcpping和防火墙策略 - 最易被忽略的点:
V$ARCHIVED_LOG里DEST_ID=2(备库)的ARCHIVED='YES'但APPLIED='NO',且COMPLETION_TIME比主库V$LOG_HISTORY同序列FIRST_TIME晚>10秒——这说明数据已到备库磁盘,但MRP还没开始应用,问题在备库I/O或CPU,和网络无关
跨网段DG的稳定性,80%取决于中间链路是否允许TCP window scaling和SACK透传,剩下20%才是Oracle层参数。调完tcp_rmem发现没用,第一反应不该是再加大,而是抓包确认SYN包里有没有wscale和SACK_PERM标志位。











