data guard需调大sdu因传输redo数据流而非单条sql,默认8kb易致分包增多、tcp开销上升;实测sdu=32767可减少30%–50%系统调用,但须主备监听三端同步配置sdu及配套缓冲区,并避免全局修改sqlnet.ora。
直接调到 sdu=32767 是最稳妥的起点,但必须避开全局改 sqlnet.ora 这个坑。
为什么Data Guard特别需要调大SDU
Oracle Data Guard传输的是redo数据流,不是单条SQL结果。默认SDU(Session Data Unit)是8KB(12c),而一个归档日志块可能远超这个大小。网络栈会把大块redo切成多个小包发送,增加系统调用次数和TCP头开销。实测中,SDU=32767能让同样量的redo减少约30%–50%的send()系统调用,尤其在高延迟WAN链路下效果明显。
注意:SDU实际生效值取客户端与服务端配置的较小者。所以主库、备库、监听器三端都要检查。
只改tnsnames.ora和listener.ora,别碰sqlnet.ora
全局改sqlnet.ora里的DEFAULT_SDU_SIZE会影响所有连接——包括应用直连、DBA工具、监控脚本,容易引发意外超时或内存抖动。
- 在
tnsnames.ora里为DG专用连接描述符加SDU:(DESCRIPTION = (SDU=32767) (ADDRESS=(PROTOCOL=TCP)(HOST=standby-host)(PORT=1521)) (CONNECT_DATA=(SERVICE_NAME=orcl_dg))) - 在
listener.ora里为DG实例注册加SDU:(SID_DESC = (SDU=32767) (SID_NAME=orcl) (ORACLE_HOME=/u01/app/oracle/product/12.1.0/dbhome_1)) - 改完必须重启
lsnrctl reload,否则监听器不读新配置
SDU和TCP缓冲区要配套调,否则白忙
光调SDU不够。如果OS层的TCP接收/发送缓冲区(RECV_BUF_SIZE/SEND_BUF_SIZE)太小,大SDU会被截断或降级回默认值。Oracle建议这两者至少设为SDU的1.5倍以上。
- 在
tnsnames.ora连接串里补上:(RECV_BUF_SIZE=49152) (SEND_BUF_SIZE=49152) - 在
listener.ora的ADDRESS段也加上:(ADDRESS=(PROTOCOL=TCP)(HOST=...)(PORT=1521)(RECV_BUF_SIZE=49152)(SEND_BUF_SIZE=49152)) - Linux下还要确认内核参数没卡死:检查
/proc/sys/net/core/rmem_max和wmem_max是否≥49152,否则配置不生效
验证SDU是否真生效了
不能只看配置文件。得用trcasst -t或tcpdump抓包确认实际TCP payload大小,或者查动态视图:
在主库执行:SELECT * FROM v$session_connect_info WHERE sid = (SELECT sid FROM v$session WHERE program LIKE '%LGWR%') AND network_service_banner LIKE '%SDU%';
返回结果里network_service_banner字段应含SDU=32767。如果还是SDU=8192,说明某端没配对,或监听器没重载。
最容易被忽略的是:动态服务注册(即没在listener.ora里显式写SID_DESC)的实例,会无视tnsnames里的SDU,只认sqlnet.ora的DEFAULT_SDU_SIZE——这时你必须在listener.ora里补全静态注册。











