SQL*Net message from client 等待既非纯空闲也非必然故障,本质是Oracle等待客户端发起下一条OCI调用;需结合avg_wait、waits、time_waited及SQL执行耗时综合判断网络延迟或应用逻辑瓶颈。
SQL*Net message from client 等待到底是空闲还是问题?
它**既不是纯空闲,也不一定代表数据库有问题**——本质是 oracle 在等客户端发下一条命令,等待时间 = 网络传输 + 客户端处理 + 应用逻辑停顿。如果这个等待占 awr 报告 top 5,优先排查的不是数据库,而是应用怎么用连接、有没有长事务、是否批量提交不足。
怎么区分是网络延迟还是应用慢?
看 SQL*Net message from client 的平均等待时间(avg_wait)和总等待次数(waits)的组合:
- 平均等待 INSERT,不是网络问题,是应用设计问题
- 平均等待 >100ms 且波动大 → 检查客户端到 DB 服务器的网络:用
ping、traceroute、tcpdump看丢包或抖动;注意中间有无防火墙、SSL 代理、NAT 设备 - 平均等待稳定在 20–50ms,且集中在某几个
SQL_ID→ 很可能是这些 SQL 对应的业务逻辑在客户端做了耗时操作(如 Java 里 ResultSet 遍历后又调了外部 HTTP 接口)
AWR 里哪些字段真正有用?
别只盯着“等待事件”总时间。重点看三列:avg_wait(单位毫秒)、time_waited(秒)、waits(次数)。再关联 DBA_HIST_SQLSTAT 查对应 SQL 的 elapsed_time 和 cpu_time:
- 如果
elapsed_time远大于cpu_time+ 所有非空闲等待之和 → 剩余时间大概率就是SQL*Net message from client占的,说明 SQL 执行快,但应用没及时发下一条 -
executions少但waits极高 → 客户端可能用了 autocommit=false 却忘了commit,导致连接长期挂起 - 同一
SQL_ID在不同 AWR 快照中avg_wait突增 → 不是数据库变慢,是那段时间客户端环境变了(比如新上线的 App Server JVM GC 加剧、线程池打满)
容易被忽略的底层机制
Oracle 不会主动“推送”数据给客户端;每次 fetch、execute、parse 后,都进等待状态,直到收到下一个 OCI 调用。这意味着:
- 即使 SQL 执行完,只要客户端没发
OCIStmtFetch2或OCITransCommit,连接就卡在SQL*Net message from client - Java 的
ResultSet.next()如果一次只取一行,且每行后做复杂处理,等待就会被拆成 N 次小等待,avg_wait看着不高,但总耗时惊人 - Oracle 19c+ 的
SQL*Net break/reset to client出现增多,往往意味着客户端异常断连,此时SQL*Net message from client可能被截断统计,数值失真
真正难定位的,从来不是等待本身,而是客户端那一端谁在 hold connection、谁在 sleep、谁在等下游接口——数据库日志里看不到这些。

















