ASH中SQL*Net message from client长时间等待(>100ms)、program匹配java@、blocking_session为空三者交叉,可锁定Java连接未关闭的可疑会话,因其反映会话长期空闲挂起而非正常交互。

直接结论:ASH里看不到“连接没关”,但能通过SQL*Net message from client长时间等待 + program匹配java@ + blocking_session IS NULL三者交叉锁定可疑会话。
为什么SQL*Net message from client是关键信号
Java应用连接未关闭,数据库端最典型的表征不是报错,而是会话长期处于“等客户端发下一条命令”状态。ASH中event = 'SQL*Net message from client'正是这个状态的采样记录。但它本身不区分正常空闲和异常滞留——必须加条件过滤才有效。
- 只查
event = 'SQL*Net message from client'会混入大量健康连接(比如HTTP长连接保活) - 必须叠加
session_state = 'WAITING'且time_waited > 100000(即>100ms),排除瞬时网络抖动 -
sql_id IS NULL是硬性要求:有sql_id说明正在执行SQL,不属于“连上就挂起”场景 - 时间窗别拉太宽,
SAMPLE_TIME > SYSDATE - 5/1440(最近5分钟)足够,老数据干扰大
如何从program字段识别Java应用真实来源
Oracle默认把JDBC连接记为program = 'JDBC Thin Client'或java@hostname,但生产环境常被覆盖。真正可靠的是结合module和action字段,它们由应用代码显式设置(如Spring Boot的spring.datasource.hikari.data-source-properties.oracle.jdbc.defaultRowPrefetch=100不影响这个)。
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
- 优先查
module非空且含spring、quarkus、vertx等框架名的会话 - 若
module为空,再看program是否为java@开头,或包含服务名(如order-svc) - 警惕
program = 'oracle@'+machine指向应用服务器IP:这是JDBC直连未设setClientInfo的典型表现 - 不要依赖
username判断——连接池共用账号很常见
为什么blocking_session IS NULL比阻塞关系更重要
连接未关闭的源头,本质是“没人等它,但它自己卡着不走”。这类会话在ASH里表现为blocking_session IS NULL(不是阻塞者,也不是被阻塞者),却持续采样到SQL*Net message from client事件。这和事务锁、DDL阻塞等场景有根本区别。
- 如果
blocking_session非空,优先排查锁或DDL问题,不是连接泄漏 - 重点筛出
COUNT(*)高且AVG(time_waited)也高的machine+program组合——同一台机器上多个Java进程共用连接池时,这里会集中爆发 - 查出SID后,立刻连上去执行:
SELECT sql_text FROM v$sqlarea WHERE sql_id = (SELECT prev_sql_id FROM v$session WHERE sid = &sid),确认最后执行的是否是SELECT 1 FROM DUAL或心跳SQL - 注意RAC环境:必须查
GV$ACTIVE_SESSION_HISTORY,否则跨节点的泄漏会漏掉
真正难定位的不是单个泄漏连接,而是连接池配置错误(如maxLifetime设为0导致连接永不回收)或应用未调用Connection.close()却被try-with-resources掩盖。ASH只能告诉你“谁还连着”,不能代替代码审计——但至少能帮你快速圈定哪台机器、哪个服务需要优先检查。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










