查活跃会话最可靠依据是STATUS = 'ACTIVE',表示正执行SQL;需排除后台进程(type != 'BACKGROUND'),结合event判断等待事件,注意权限、RAC环境用gv$session及sql_id/prev_sql_id配合v$sql查实际语句。
直接查 v$session 就能知道谁在连、连得是否活跃,但 status 字段的含义容易误读——比如 inactive 不代表“已断开”,而是“没在跑 sql”,它仍占着连接资源。
怎么筛出真正干活的活跃会话
只看 STATUS = 'ACTIVE' 是最常用也最可靠的判断依据,但它只表示该会话当前正执行某条 SQL(哪怕只是 SELECT 1 FROM DUAL)。别被 LOGON_TIME 或 LAST_CALL_ET 迷惑——前者是登录时间,后者是上一次调用距今秒数,对判断“此刻是否活跃”没直接帮助。
SELECT sid, serial#, username, program, machine, sql_id, event FROM v$session WHERE status = 'ACTIVE' AND type != 'BACKGROUND';- 加
AND type != 'BACKGROUND'排除 Oracle 自身后台进程(如 DBWR、LGWR),避免干扰 -
event字段能看出卡在哪:如果是SQL*Net message from client,说明 SQL 已执行完,正在等客户端发下一条;如果是db file sequential read,大概率真在 IO - 注意:
sql_id为空时,可能刚连上来还没执行任何语句,或执行的是匿名 PL/SQL 块(此时需查prev_sql_id)
为什么查到的 ACTIVE 会话比应用连接池配置数还多
这是典型的应用未正确归还连接导致的“连接泄漏”。Oracle 不会主动回收空闲但未关闭的 INACTIVE 会话,而某些框架(如老版本 MyBatis + Druid)在异常路径下可能跳过 close() 调用。
- 检查
v$session中相同username+machine+program的INACTIVE会话是否长期存在(last_call_et > 3600) - 对比应用侧连接池的
maxActive和数据库侧processes参数,若前者远小于后者但会话数持续上涨,基本可锁定是应用端问题 -
ALTER SYSTEM KILL SESSION只是标记,真实清理要等 PMON,所以杀完立刻查v$session还能看到STATUS = 'KILLED'的记录
查活跃会话时容易忽略的权限和视图差异
普通用户默认查不到其他用户的 v$session 记录,只能看到自己。想查全部,必须有 SELECT_CATALOG_ROLE 或显式授权:
-
GRANT SELECT ON v_$session TO your_user;(注意是v_$session,不是v$session;后者是同义词,需额外授权) - RAC 环境下要用
gv$session替代v$session,否则只看到本实例的会话 -
v$session中的sid是会话 ID,audsid才是SYS_CONTEXT('USERENV', 'SESSIONID')返回的值,两者不等价,别混用
真正难处理的不是查得到查不到,而是看到一堆 ACTIVE 却不知道它在跑什么——这时候得立刻关联 v$sql 或 v$sqlarea 拿 sql_text,但要注意文本可能被截断,且历史 SQL 得靠 prev_sql_id 回溯。


















