sql*net message from client等待事件本身不表示网络延迟,而是oracle空闲等待客户端指令;真瓶颈需结合avg_wait(>100ms且波动大才疑网络)、ash中avg(time_waited)/1000趋势、machine/program定位及tnsping/sqlplus基线对比综合判断。
直接查 sql*net message from client 等待事件本身不能断定是网络延迟——它只是 oracle 等客户端发下一条命令的空闲状态,真瓶颈在客户端处理逻辑或链路质量,必须结合等待时长、分布特征和交叉验证才能定位。
怎么看 SQL*Net message from client 是真网络延迟?
这个等待事件在 AWR/ASH 中占比高不等于网络慢;关键看它的平均单次等待时间(avg_wait 或 ASH 中的 time_waited)是否异常拉长:
- 平均等待 :正常,大概率是客户端快速循环调用(如轮询)
- 平均等待 20–100ms 且稳定:需检查客户端所在主机的 JVM GC、线程池打满、或 ResultSet 处理逻辑(比如 Java 每行后调 HTTP 接口)
- 平均等待 > 100ms 且波动大:才值得怀疑网络层,尤其是同一
machine下多个会话同时出现该现象 - 注意:
time_waited单位是微秒,ASH 查询中记得除以 1000 转成毫秒
为什么只查 ASH 容易误判?
ASH 是每秒采样一次,且只记录 session_state = 'WAITING' 的瞬间快照。如果客户端只是偶尔卡顿(比如某次 fetch 后 sleep(5)),ASH 可能只捕获到其中一两帧,导致 time_waited 看起来不高,但真实阻塞已发生:
- 不要只依赖
COUNT(*),要算AVG(time_waited)/1000并按SAMPLE_TIME分组看趋势 - 过滤条件必须加严:
event = 'SQL*Net message from client'ANDsession_state = 'WAITING'ANDsql_id IS NULL(排除正在执行 SQL 的干扰) - 用
machine和program替代client_id,因为后者常为空;例如program = 'java@app01'比 IP 更可靠 - 若发现大量会话集中在同一分钟内出现该等待,且
LAST_CALL_ET > 300(v$session),基本可排除数据库内部问题
怎么排除应用层干扰,确认真是链路问题?
很多“网络慢”其实是客户端自己卡住,不是 Oracle 或中间设备的问题:
- 用
tnsping <tns_alias></tns_alias>测 TCP 连通性和基础延迟,避开 Oracle 认证开销 - 用
sqlplus /@<tns_alias></tns_alias>执行SELECT 1 FROM DUAL,记录响应时间基线;对比同网段其他服务(如 Redis、HTTP API)延迟 - 检查客户端是否启用了 SSL/TLS 加密、代理、或防火墙策略(尤其 F5/Nginx 健康检查探针被拦截会导致连接假死)
- 确认是否用了连接池:Druid/HikariCP 的
maxLifetime、keepAlive配置不当,会引发频繁重连 + TCP TIME_WAIT 暴涨,服务端端口耗尽 - Java 应用里
ResultSet.next()如果逐行处理且每行后有日志或远程调用,等待会被拆成 N 次小等待,avg_wait看着低,但总耗时惊人
真正难定位的,从来不是 SQL*Net message from client 这个等待本身,而是客户端那一端谁在 hold connection、谁在 sleep、谁在等外部响应——Oracle 只负责等,不负责猜。











