SQL*Net message to client等待时间长通常非数据库性能问题,多因客户端未及时读取数据或网络延迟;占比超50%且单次超100ms才需深挖,优先检查v$session的PROGRAM和STATE。
SQL*Net message to client 等待时间长,先看是不是空闲等待
这个等待事件本身不一定是性能问题——它只表示服务进程刚把数据发给客户端,正在等 tcp 层确认(ack)或下一条指令。如果 sql*net message to client 占总等待时间超过 50%,且单次等待常达 100ms 以上,才值得深挖;否则大概率是客户端没及时读数据,或者网络链路有延迟。
用这条 SQL 快速判断是否属于“假高”:
SELECT event, total_waits, time_waited_ms, ROUND(100*time_waited_ms/SUM(time_waited_ms) OVER(),2) pct FROM v$system_event WHERE event = 'SQL*Net message to client';
- OLTP 系统健康范围是 10~30%,占比 >50% 才算异常
- 查
v$session时若state是WAITING但seconds_in_wait持续增长,说明客户端卡住了 -
PROGRAM字段值为JDBC Thin Client或sqlplus.exe时,优先排查客户端侧行为(比如 Java 应用没调用ResultSet.next())
SDU 太大或太小都会拖慢 SQL*Net message to client
SDU(Session Data Unit)是 Oracle 在 TCP 层打包数据的单位,默认 8192 字节。设得太大,客户端接收缓冲区可能溢出或处理不过来;设得太小,又会导致大量小包、增加往返次数和 TCP 开销。
- WAN 环境、高 RTT(>100ms)场景建议调大 SDU:在
sqlnet.ora加DEFAULT_SDU_SIZE = 16384 - 但别盲目设到 65535(共享服务器默认值),这会显著增加 PGA 内存占用,尤其连接数多时
- 实际生效值取客户端与服务端
DEFAULT_SDU_SIZE的较小者,所以两端都要检查 - 验证是否起效:用
trcsess+tkprof看 trace 中SDU size和predominant message size差值,若就说明 SDU 匹配度差,需要调整
TCP_NODELAY 和压缩参数容易适得其反
很多人一看到 “网络慢” 就开压缩、关 Nagle 算法,但在 Oracle 12c 上,这些操作不加区分反而加重负担。
-
SQLNET.COMPRESSION = on会触发 CPU 压缩计算,若客户端 CPU 已饱和,SQL*Net message to client反而更长 -
SQLNET.COMPRESSION_LEVEL = HIGH基本只适合带宽极窄、CPU 充裕的离线传输场景,OLTP 下严禁使用 -
TCP.NODELAY不是 sqlnet.ora 参数,它是操作系统级设置;Oracle 客户端不直接控制它,强行在sqlnet.ora写TCP.NODELAY=ON会被忽略 - 真正影响发送延迟的是 SDU + OS TCP 缓冲区 + 客户端应用消费速度,不是要不要延迟合并
Java 应用不读 sqlnet.ora,必须显式传参
绝大多数 JDBC Thin 连接根本不会加载本地 sqlnet.ora,所以你在 $ORACLE_HOME/network/admin 下改了 DEFAULT_SDU_SIZE 或 SQLNET.COMPRESSION,对 Spring Boot 应用完全无效。
- 必须通过连接属性传:例如
jdbc:oracle:thin:@//host:1521/orcl?oracle.net.CONNECT_TIMEOUT=5&oracle.net.SDU_SIZE=16384 -
oracle.net.CONNECT_TIMEOUT是 JDBC 特有参数,对应客户端建连超时,和 sqlnet.ora 里的CONNECT_TIMEOUT(12cR1+ 才支持)不是一回事 - 别信网上“加 -Doracle.net.tns_admin=... 就能读 sqlnet.ora”的说法——JDBC Thin 不走 Oracle Net stack 的解析逻辑,只认 URL 参数
- 验证方式:抓包看 TCP 握手后第一个 Oracle 数据包的长度,是否接近你设的 SDU 值
最常被忽略的一点:这个等待高,90% 情况下问题不在数据库,而在客户端有没有及时 pull 数据。盯住 v$session 的 PROGRAM 和 STATE,比调任何 TNS 参数都管用。











