单独查V$ACTIVE_SESSION_HISTORY会漏掉长期INACTIVE的“僵尸会话”,因其只采样SESSION_STATE为'ON CPU'或'WAITING'的活跃会话,而空闲会话不被记录。
只查 v$active_session_history 会漏掉真正危险的长连接——那些早已空闲、不活动、却死占着连接数和锁资源的会话。
为什么单独查 ASH 找不到“长连接”
ASH 每秒采样一次,且只记录 SESSION_STATE = 'ON CPU' 或 'WAITING' 的活跃会话。一旦事务结束、SQL 执行完、进入空闲状态,该会话就不再被采样。哪怕它已连了 3 小时、STATUS = 'INACTIVE'、LAST_CALL_ET > 10800(3 小时),ASH 里也几乎为零记录。
这类会话的真实连接时长只能靠 V$SESSION.LOGON_TIME 算出来:SYSDATE - LOGON_TIME;而 LAST_CALL_ET 只是“上一次调用结束至今”,不是连接时长。
- 常见表现:
STATUS = 'INACTIVE'+EVENT = 'SQL*Net message from client'+MODULE固定(如'JDBC Thin Client') - 容易误判:把
V$SESSION中TYPE = 'BACKGROUND'或USERNAME IS NULL的后台进程当成长连接,需排除 - RAC 环境下必须加
INST_ID过滤,否则跨节点结果错乱
怎样用 V$SESSION 快速筛出可疑长连接
先锁定“活着但不动”的会话,再决定是否深入查 ASH 行为轨迹。执行以下查询(单位:秒):
SELECT SID, SERIAL#, USERNAME, STATUS, LOGON_TIME, LAST_CALL_ET, MODULE, CLIENT_IDENTIFIER, SQL_ID, EVENT FROM V$SESSION WHERE STATUS = 'INACTIVE' AND LAST_CALL_ET > 1800 AND USERNAME IS NOT NULL AND TYPE = 'USER';
关键点:
-
LAST_CALL_ET > 1800是初步阈值(30 分钟空闲),生产环境可按需调高到7200(2 小时) -
EVENT = 'SQL*Net message from client'基本确认客户端未发新请求,连接悬空 -
CLIENT_IDENTIFIER为空或恒定,常说明应用未正确 close() 连接,尤其在连接池场景 - 若
SQL_ID非空,说明最后一次执行的 SQL 还在共享池中,可顺手查其执行计划
什么时候该把 V$SESSION 结果关联进 ASH 查行为
仅当怀疑这些长连接“偶发活跃并拖慢系统”时,才用它们的 SESSION_ID 和 SESSION_SERIAL# 去翻 ASH,看历史有没有高耗时操作。
例如查某会话过去一小时内是否曾触发大量逻辑读或锁等待:
SELECT SAMPLE_TIME, SQL_ID, EVENT, P1TEXT, P1, P2TEXT, P2, TIME_WAITED FROM V$ACTIVE_SESSION_HISTORY WHERE SESSION_ID = <sid> AND SESSION_SERIAL# = <serial#> AND SAMPLE_TIME > SYSDATE - 1/24;
- 必须加
SAMPLE_TIME > SYSDATE - 1/24,否则默认可能只返回最近几分钟(ASH 内存 buffer 会滚动覆盖) - 若查不到数据,不是没发生,而是该会话在采样瞬间始终处于空闲态——这反而印证了它是“静默型长连接”
- 重点关注
EVENT是否含'enq: TX%'、'library cache lock'或'latch: cache buffers chains',这些是长连接突然活过来后最容易引发抖动的等待类型
查不到 ASH 数据?先确认你没踩这几个坑
ASH 不是日志,是内存采样快照,很多“查不到”问题其实和 SQL 写法或环境配置强相关:
- 时间条件写死字符串(如
'2026-06-03 14:00:00')→ 改用SAMPLE_TIME > SYSDATE - INTERVAL '60' MINUTE,避免时区/NLS 导致偏差 - RAC 环境下查
V$ACTIVE_SESSION_HISTORY→ 只能看到本节点,必须换GV$ACTIVE_SESSION_HISTORY并加INST_ID -
STATISTICS_LEVEL = 'BASIC'→ ASH 被完全禁用,检查SHOW PARAMETER statistics_level,应为TYPICAL或ALL - 实例刚重启过 →
V$ACTIVE_SESSION_HISTORY全空,只能查磁盘视图DBA_HIST_ACTIVE_SESS_HISTORY,但采样粒度是 10 秒,细节已丢失
最易被忽略的一点:长连接本身不可怕,可怕的是它持有未提交事务、未释放的行锁、或阻塞了 DDL —— 这些状态在 V$SESSION 里有迹可循(如 ROW_WAIT_OBJ# 非空、SQL_ID 对应事务未提交),但不会出现在 ASH 里。


















