4. 会话与连接监控

会话是Oracle数据库中最贴近“用户正在做什么”的观测对象。一个客户端进程通过监听器建立连接后,会在数据库内部形成一个会话,并由一个服务端进程为其服务。会话监控的目标不是简单数一数当前有多少连接,而是回答四个运维问题:连接总量是否逼近上限、哪些会话正在真正消耗资源、连接从哪里来、哪些会话在空闲或阻塞别人。本节围绕V$SESSION、V$PROCESS、V$RESOURCE_LIMIT三个核心视图展开,给出可直接执行的查询与判读方法。

三个视图的分工与关联

V$SESSION是会话级主视图,每一行代表一个会话,关键字段包括SID、SERIAL#、USERNAME、STATUS、MACHINE、PROGRAM、MODULE、SQL_ID、EVENT、WAIT_CLASS、LAST_CALL_ET、BLOCKING_SESSION、PADDR等。STATUS常见取值为ACTIVE(正在执行或等待CPU/资源)、INACTIVE(等待下一条语句)、KILLED等。V$PROCESS是操作系统进程视图,记录服务端进程的SPID、PGA占用、进程镜像等,通过V$SESSION.PADDR = V$PROCESS.ADDR关联,从而把“数据库会话”映射到“操作系统进程”,便于在OS层定位CPU或内存消耗。V$RESOURCE_LIMIT则给出资源上限与当前使用量,其中与连接最相关的是sessions、processes、transactions等资源项,字段包括RESOURCE_NAME、CURRENT_UTILIZATION、MAX_UTILIZATION、LIMIT_VALUE、INITIAL_ALLOCATION。

会话监控三视图关联与判读路径 客户端连接来源 MACHINE / PROGRAM MODULE / USERNAME 按来源聚合计数 识别异常来源 V$SESSION(会话主表) SID / SERIAL# / STATUS SQL_ID / EVENT / WAIT_CLASS LAST_CALL_ET(空闲时长) BLOCKING_SESSION(阻塞者) PADDR → 关联进程 TYPE='USER' 过滤后台 STATUS='ACTIVE' 判活跃 V$PROCESS(OS进程) ADDR ← 与PADDR关联 SPID(OS进程号) PGA_USED_MEM / PGA_ALLOC PROGRAM / IMAGE 定位CPU/内存消耗进程 配合OS命令top/ps V$RESOURCE_LIMIT(资源上限与使用量) RESOURCE_NAME:sessions / processes / transactions CURRENT_UTILIZATION:当前已用 MAX_UTILIZATION:历史峰值 LIMIT_VALUE:上限(0表示无限制) 使用率 = CURRENT_UTILIZATION / LIMIT_VALUE 判读结论 使用率 > 80%:预警扩容 ACTIVE 突增:定位SQL_ID 空闲会话多:考虑回收 BLOCKING_SESSION 非空:阻塞链 来源异常:核查MACHINE

会话总量与资源上限监控

连接数是否健康,不能只看V$SESSION的行数,必须与V$RESOURCE_LIMIT中的sessions、processes上限对照。下面这条查询把当前会话数、活跃会话数、上限与使用率一次算出:

SELECT r.RESOURCE_NAME,
       r.CURRENT_UTILIZATION AS cur_used,
       r.MAX_UTILIZATION     AS max_used,
       r.LIMIT_VALUE         AS limit_val,
       ROUND(r.CURRENT_UTILIZATION /
             NULLIF(r.LIMIT_VALUE,0) * 100, 2) AS used_pct
FROM   V$RESOURCE_LIMIT r
WHERE  r.RESOURCE_NAME IN ('sessions','processes','transactions')
ORDER  BY used_pct DESC;

SELECT COUNT(*) AS total_sess,
       SUM(CASE WHEN STATUS='ACTIVE' THEN 1 ELSE 0 END) AS active_sess,
       SUM(CASE WHEN STATUS='INACTIVE' THEN 1 ELSE 0 END) AS inactive_sess
FROM   V$SESSION
WHERE  TYPE = 'USER';

判读要点:LIMIT_VALUE为0表示该资源无限制,此时使用率无意义,应转而关注绝对增长趋势。经验阈值上,sessions使用率持续超过80%就应预警,因为连接建立、后台进程、并行执行都会额外占用会话槽位,接近上限时新连接会报ORA-00018(maximum number of sessions exceeded)或ORA-00020(maximum number of processes exceeded)。MAX_UTILIZATION反映历史峰值,若它已接近LIMIT_VALUE,说明系统曾经逼近过上限,即使当前不高也需要扩容或治理连接池。

活跃会话与连接来源分析

活跃会话是真正占用CPU和等待资源的会话。按来源聚合可以快速发现异常客户端,例如某个应用服务器连接池配置过大,或某台机器出现连接泄漏:

SELECT MACHINE, PROGRAM, USERNAME,
       COUNT(*) AS sess_cnt,
       SUM(CASE WHEN STATUS='ACTIVE' THEN 1 ELSE 0 END) AS active_cnt
FROM   V$SESSION
WHERE  TYPE = 'USER'
GROUP  BY MACHINE, PROGRAM, USERNAME
ORDER  BY sess_cnt DESC;

SELECT SID, SERIAL#, USERNAME, STATUS, SQL_ID,
       EVENT, WAIT_CLASS, LAST_CALL_ET, BLOCKING_SESSION
FROM   V$SESSION
WHERE  TYPE='USER' AND STATUS='ACTIVE'
ORDER  BY LAST_CALL_ET DESC;

如果某台MACHINE的会话数远超其他节点,且PROGRAM指向同一个连接池,通常说明该池的maxPoolSize或initialSize设置过大,或应用未正确关闭连接。此时应结合应用侧连接池配置核对,而不是直接在数据库端杀会话。对于ACTIVE会话,重点看EVENT和WAIT_CLASS:若大量会话等待db file scattered read、log file sync等,说明瓶颈在I/O或提交频率;若等待enq: TX - row lock contention,则进入阻塞分析。

空闲会话与阻塞会话识别

空闲会话本身不消耗CPU,但占用会话槽位和PGA。LAST_CALL_ET表示会话最后一次调用至今的秒数,可用于识别长时间空闲连接:

SELECT SID, SERIAL#, USERNAME, MACHINE, PROGRAM,
       LAST_CALL_ET, STATUS
FROM   V$SESSION
WHERE  TYPE='USER' AND STATUS='INACTIVE'
  AND  LAST_CALL_ET > 3600
ORDER  BY LAST_CALL_ET DESC;

对这类会话,应先确认是否属于连接池保活连接,再决定是否通过资源计划或IDLE_TIME限制回收。阻塞会话的识别依赖BLOCKING_SESSION字段,它指向阻塞当前会话的SID。下面查询直接列出阻塞者与被阻塞者:

SELECT s.SID AS blocked_sid, s.USERNAME AS blocked_user,
       s.BLOCKING_SESSION AS blocker_sid,
       b.USERNAME AS blocker_user,
       b.SQL_ID   AS blocker_sql,
       s.EVENT, s.SECONDS_IN_WAIT
FROM   V$SESSION s
JOIN   V$SESSION b ON b.SID = s.BLOCKING_SESSION
WHERE  s.BLOCKING_SESSION IS NOT NULL;

若阻塞链较长,可用START WITH ... CONNECT BY沿BLOCKING_SESSION向上追溯根阻塞者。定位到根会话后,先查其SQL_ID对应的SQL文本和等待事件,判断是长事务未提交还是锁竞争,再决定提交、回滚或终止。终止会话使用ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE,执行后应复查V$SESSION确认会话消失、阻塞链解除。

会话到OS进程的映射

当需要确认某个会话对应的操作系统进程时,通过PADDR关联V$PROCESS取得SPID:

SELECT s.SID, s.SERIAL#, s.USERNAME, s.STATUS,
       p.SPID, p.PGA_USED_MEM, p.PGA_ALLOC_MEM
FROM   V$SESSION s
JOIN   V$PROCESS p ON p.ADDR = s.PADDR
WHERE  s.TYPE='USER' AND s.STATUS='ACTIVE'
ORDER  BY p.PGA_USED_MEM DESC;

拿到SPID后,可在操作系统层用top -p、ps -p等命令观察该进程的CPU与内存占用,实现数据库视图与OS监控的联动。PGA_USED_MEM偏高且持续增长的会话,往往对应排序、哈希连接等大内存操作,需要结合SQL执行计划评估是否调整PGA_AGGREGATE_TARGET或优化SQL。

建议把上述查询固化为日常巡检脚本:每5分钟采集一次sessions使用率、ACTIVE会话数、按MACHINE聚合的连接数、阻塞会话数,写入监控表或推送至告警平台。当sessions使用率超过80%、ACTIVE会话数突增50%以上、或出现阻塞链时触发告警,可显著缩短故障发现时间。
不要仅凭V$SESSION行数判断连接是否超限,必须结合V$RESOURCE_LIMIT的LIMIT_VALUE;也不要在未确认会话归属的情况下批量KILL SESSION,尤其是连接池会话,误杀可能引发应用大面积重连甚至雪崩。