应先查v$session和v$process实时快照,与processes参数上限比对;若活跃会话长期超70%才需深挖,短时飙升多因连接未复用而非数据库瓶颈。
怎么判断连接数是否真高,而不是误报
别一看到“连接多”就翻ash。先查 v$session 和 v$process 的实时快照,再和 processes 参数上限比——这才是唯一靠谱的基准。
执行这两条:
select count(*) from v$session where status = 'ACTIVE'; select value from v$parameter where name = 'processes';
- 如果活跃会话长期超过
PROCESSES值的 70%,才值得往下深挖 - 如果只是短时飙升(比如应用重启后批量建连),大概率是连接未复用,不是数据库瓶颈
-
V$SESSION里 STATUS = 'INACTIVE' 但 LAST_CALL_ET > 3600 的会话,要重点盯:它们不占ASH采样,却真实占用PROCESSES配额
ASH里哪些字段能定位并发卡点,哪些不能
V$ACTIVE_SESSION_HISTORY 不是数连接的工具,是看“谁在抢资源”的。关键就三个字段:
-
SESSION_ID+SESSION_SERIAL#:组合唯一标识一个会话,避免把同一会话的多次采样当多个连接 -
EVENT:比如高频出现enq: TX - row lock contention或db file sequential read,说明锁或IO拖慢了响应,导致连接堆积 -
SQL_ID:关联V$SQL查具体语句,重点看ELAPSED_TIME / EXECUTIONS比值——高耗时、低频次的SQL最容易卡住连接
别跑 COUNT(*) GROUP BY SAMPLE_TIME 画曲线,那只是自欺欺人。
为什么直接查ASH可能漏掉真正的问题会话
ASH每秒采样一次,只保留内存中约1小时数据(默认),两个硬伤让它天然不全:
- 已断开但没清理的会话(
STATUS = 'INACTIVE'且LOGON_TIME很老)根本不会进ASH,却仍占着PROCESSES配额 - 如果数据库启用了
_ash_sampling_mode=0(罕见但存在),ASH只采前台会话,后台进程类连接完全不可见
必须交叉验证:V$SESSION 看全量状态、V$SESSION_CONNECT_INFO 看客户端IP和协议、操作系统级 netstat -an | grep :1521 | wc -l 看真实TCP连接数。
怎样从ASH识别连接泄漏,而不是临时高峰
连接泄漏的核心特征是:存活时间长 + 活动度低 + 客户端不变。在ASH中筛这个组合:
SELECT SESSION_ID, SESSION_SERIAL#, MAX(SAMPLE_TIME) - MIN(SAMPLE_TIME) AS DURATION,
COUNT(*) AS SAMPLES, MAX(SQL_ID) AS LAST_SQL
FROM V$ACTIVE_SESSION_HISTORY
WHERE SESSION_ID IN (
SELECT SID FROM V$SESSION
WHERE STATUS = 'INACTIVE'
AND LAST_CALL_ET > 3600
)
GROUP BY SESSION_ID, SESSION_SERIAL#
HAVING COUNT(*) INTERVAL '30' MINUTE;
COUNT(*) 表示采样极少,说明会话几乎不干活-
DURATION > 30 MINUTE表示它挂了很久,不是瞬时请求 - 结果里反复出现同一
MACHINE或PROGRAM字段,基本就是应用侧没 close() 连接
ASH本身不存客户端名,V$ACTIVE_SESSION_HISTORY 里只有 USER_ID,查用户名得手动 JOIN DBA_USERS,否则永远对不上人。











