oracle ash不记录tcp连接层等待事件,仅捕获sql*net message from client等oracle内核感知的等待;其长等待多源于客户端至db服务器链路问题,如tcp重传、防火墙拦截或连接池配置不当。
oracle 本身不通过 ash 记录 tcp 连接层的等待事件。你查 v$active_session_history 或 gv$active_session_history,永远看不到 tcp connection timeout、socket read/write 这类操作系统级网络问题——ash 只捕获 oracle 内核感知到的等待,比如 sql*net message from client(客户端响应慢)、sql*net break/reset to client(连接异常中断),但这些是结果,不是根源。
为什么查不到 TCP 层阻塞?
Oracle 的网络通信由 Oracle Net Services(即 SQL*Net)封装,底层依赖 OS socket 调用。一旦发生 TCP 重传、SYN 超时、防火墙拦截、中间设备丢包,Oracle 进程本身通常不感知具体原因,只会表现为:
-
SQL*Net message from client等待时间异常拉长(time_waited达几百毫秒甚至秒级) - 大量会话卡在
SQL*Net break/reset to client,且blocking_session为空 - 同一客户端 IP 出现多个会话同时卡住,而其他 IP 正常
这些现象提示问题出在客户端到 DB Server 的链路上,而非数据库内部。
如何用 ASH 间接定位网络瓶颈?
重点不是找“TCP”,而是找“谁在等、等了多久、从哪来”:
- 过滤
event = 'SQL*Net message from client',按client_id或machine分组统计平均time_waited(单位:微秒),>100000(即 >100ms)就值得怀疑 - 加条件
session_state = 'WAITING'且sql_id IS NULL,排除正在执行 SQL 的干扰 - 关联
userenv('ip_address')不可用,改用machine和program判断客户端类型(如python@web01、java@app02) - 执行示例:
SELECT machine, program, COUNT(*) cnt, AVG(time_waited)/1000 avg_ms<br>FROM v$active_session_history<br>WHERE event = 'SQL*Net message from client'<br> AND sample_time > SYSDATE - 1/1440 -- 最近 1 分钟<br> AND session_state = 'WAITING'<br> AND sql_id IS NULL<br>GROUP BY machine, program<br>HAVING AVG(time_waited) > 100000<br>ORDER BY avg_ms DESC;
容易被忽略的关键点
ASH 中的 SQL*Net message from client 长等待,90% 以上不是数据库问题,而是:
- 客户端应用没做连接池复用,频繁建连断连,触发 TCP TIME_WAIT 暴涨,服务端端口耗尽
- 负载均衡器(如 F5、Nginx)健康检查配置不当,TCP 探针被数据库防火墙拦截,导致连接假死
- 客户端所在宿主机网卡软中断不均,或 Docker 容器内
net.core.somaxconn过低,accept 队列溢出 - 数据库服务器
tcp_tw_reuse关闭,且并发短连接量大,TIME_WAIT 连接堆积后无法新建连接
别在数据库里调 sqlnet.ora 或改 listener.ora 参数硬扛——先抓客户端和中间链路的 tcpdump,再比对 ASH 时间戳确认是否同步恶化。











