created: 2026-04-22
updated: 2026-04-22
Oracle 会话连接查询笔记
场景:排查数据库
processes即将达到上限 / 连接池泄漏 / 定位占用连接最多的应用模块。
一、基础背景
1.1 关键视图
| 视图 | 作用 | 说明 |
|---|---|---|
v$session |
当前实例的会话信息 | 最核心视图 |
gv$session |
跨 RAC 所有实例的会话 | 多实例必用 |
v$process |
OS 进程信息 | 与 session 一一对应 |
v$resource_limit |
资源使用 vs 上限 | 查 processes/sessions 水位 |
v$active_services / gv$active_services |
当前激活的 service | 用于定位 service 所在实例 |
dba_services |
数据库级注册的 service | 静态配置 |
v$undostat |
UNDO 使用统计 | 排查 ORA-01555 / ORA-30036 |
1.2 关键字段
| 字段 | 含义 |
|---|---|
sid / serial# |
会话唯一标识,kill 用 |
inst_id |
RAC 实例号(gv$ 视图才有) |
username |
数据库用户 |
osuser |
操作系统用户 |
machine |
客户端主机名(K8s 里是 Pod 名) |
program |
客户端程序(如 JDBC Thin Client) |
module |
应用设置的模块名,最关键的定位字段 |
action |
应用内细粒度动作名 |
service_name |
会话通过哪个 service 进来 |
status |
ACTIVE 正在执行 / INACTIVE 空闲 |
last_call_et |
距上次调用的秒数,判断空闲时长 |
logon_time |
连接建立时间 |
type |
USER(业务) / BACKGROUND(后台进程) |
过滤建议 :查业务连接务必加
WHERE type='USER',排除后台进程干扰。
二、查看总量和上限
sql
-- 当前进程数 vs 参数上限
SELECT COUNT(*) FROM v$process;
SHOW PARAMETER processes
-- 一站式查 processes / sessions 水位
SELECT resource_name, current_utilization, max_utilization, limit_value
FROM v$resource_limit
WHERE resource_name IN ('processes','sessions');
判断依据:
current_utilization / limit_value > 85%→ 预警max_utilization接近limit_value→ 曾经触顶processes静态参数,改动需重启
三、按不同维度聚合查询
3.1 按 module 汇总(最常用)
sql
SELECT NVL(module,'(NULL)') AS module,
COUNT(*) AS sessions,
SUM(DECODE(status,'ACTIVE',1,0)) AS active,
SUM(DECODE(status,'INACTIVE',1,0)) AS inactive
FROM v$session
WHERE type='USER'
GROUP BY module
ORDER BY sessions DESC;
3.2 按 service_name 过滤后再看 module
sql
SELECT NVL(module,'(NULL)') AS module,
NVL(program,'(NULL)') AS program,
NVL(username,'(NULL)') AS username,
NVL(machine,'(NULL)') AS machine,
COUNT(*) AS sessions,
SUM(DECODE(status,'ACTIVE',1,0)) AS active,
SUM(DECODE(status,'INACTIVE',1,0)) AS inactive
FROM v$session
WHERE type='USER'
AND service_name='ccrb01' -- 改成你要查的服务名
GROUP BY module, program, username, machine
ORDER BY sessions DESC;
3.3 按 machine(主机/Pod)聚合
sql
SELECT machine,
COUNT(*) sessions,
COUNT(DISTINCT program) prog_cnt,
LISTAGG(DISTINCT program, ', ') WITHIN GROUP (ORDER BY program) programs
FROM v$session
WHERE type='USER'
GROUP BY machine
ORDER BY sessions DESC
FETCH FIRST 30 ROWS ONLY;
3.4 按 service 汇总
sql
SELECT service_name,
COUNT(*) sessions,
SUM(DECODE(status,'ACTIVE',1,0)) active,
SUM(DECODE(status,'INACTIVE',1,0)) inactive
FROM v$session
WHERE type='USER'
GROUP BY service_name
ORDER BY sessions DESC;
3.5 多维聚合(module + machine + program)
sql
SELECT NVL(module,'(NULL)') AS module,
NVL(program,'(NULL)') AS program,
NVL(machine,'(NULL)') AS machine,
COUNT(*) AS sessions
FROM v$session
WHERE type='USER'
GROUP BY module, program, machine
ORDER BY sessions DESC
FETCH FIRST 50 ROWS ONLY;
3.6 RAC 场景:按实例 + module
sql
SELECT inst_id,
NVL(module,'(NULL)') AS module,
COUNT(*) sessions
FROM gv$session
WHERE type='USER'
GROUP BY inst_id, module
ORDER BY inst_id, sessions DESC;
四、排查连接泄漏
4.1 长时间 INACTIVE 的空闲连接
sql
-- 空闲超过 1 小时的会话,按 module + machine 聚合
SELECT module, machine,
COUNT(*) cnt,
MIN(last_call_et) min_idle_sec,
MAX(last_call_et) max_idle_sec
FROM v$session
WHERE type='USER'
AND status='INACTIVE'
AND last_call_et > 3600
GROUP BY module, machine
ORDER BY cnt DESC;
4.2 按机器看空闲时长分布
sql
SELECT machine,
COUNT(*) cnt,
MIN(last_call_et) min_idle,
MAX(last_call_et) max_idle,
ROUND(AVG(last_call_et)) avg_idle_sec
FROM v$session
WHERE type='USER'
AND status='INACTIVE'
GROUP BY machine
ORDER BY cnt DESC;
4.3 按登录时间判断是否是启动即建
sql
SELECT machine,
TO_CHAR(MIN(logon_time),'YYYY-MM-DD HH24:MI') earliest,
TO_CHAR(MAX(logon_time),'YYYY-MM-DD HH24:MI') latest,
COUNT(*) cnt
FROM v$session
WHERE type='USER' AND module='Bootstrap'
GROUP BY machine
ORDER BY cnt DESC;
- earliest ≈ latest → 启动时一次性建满,说明
minimum-idle太大 - earliest 和 latest 差距大 → 运行期逐步增长,可能真有业务压力
五、一站式诊断 SQL(首选)
sql
SELECT NVL(username,'[SYS/BG]') AS username,
NVL(module,'(NULL)') AS module,
NVL(program,'(NULL)') AS program,
NVL(machine,'(NULL)') AS machine,
service_name,
COUNT(*) AS total,
SUM(DECODE(status,'ACTIVE',1,0)) AS active,
SUM(DECODE(status,'INACTIVE',1,0)) AS inactive,
SUM(CASE WHEN status='INACTIVE'
AND last_call_et>3600
THEN 1 ELSE 0 END) AS idle_gt_1h
FROM v$session
WHERE type='USER'
GROUP BY username, module, program, machine, service_name
ORDER BY total DESC
FETCH FIRST 50 ROWS ONLY;
六、常见 module 名含义
| module 值 | 来源 / 含义 |
|---|---|
Bootstrap |
Spring Boot 启动阶段线程名,多见于连接池初始化建立的连接 |
XxxBootApplication |
Spring Boot 应用主类名(如 ReceivableBootApplication) |
JDBC Thin Client |
未设置 module,fallback 到 program 名 |
(NULL) |
未设置 module |
SQL*Plus |
sqlplus 客户端 |
oracle@hostname (XXX) |
后台进程,不会出现在 type='USER' 查询里 |
TOAD / PLSQL Developer / Navicat |
图形客户端 |
emagent / GoldenGate |
Oracle 自家组件 |
提示 :
Bootstrap并不是业务 module,而是 Spring Boot 在bootstrap.yml/SpringApplication.run()阶段建立连接时,JDBC Driver 用主线程名打的标签。即使后面业务线程(如http-nio-xxx)复用了这些连接,module 也不会自动更新,除非代码显式调用setClientInfo。
七、应急处置
7.1 预览要 kill 的会话
sql
-- 先看看长时间空闲的会话是谁
SELECT sid, serial#, inst_id, machine, module,
ROUND(last_call_et/3600,1) idle_h
FROM gv$session
WHERE type='USER'
AND status='INACTIVE'
AND last_call_et > 7200
ORDER BY last_call_et DESC
FETCH FIRST 100 ROWS ONLY;
7.2 生成批量 KILL 语句
sql
SELECT 'ALTER SYSTEM KILL SESSION '''
||sid||','||serial#||',@'||inst_id||''' IMMEDIATE;' AS cmd
FROM gv$session
WHERE type='USER'
AND module='Bootstrap' -- 改成你要处理的 module
AND status='INACTIVE'
AND last_call_et > 3600;
⚠️
IMMEDIATE立即终止;不加IMMEDIATE会标记为 KILLED,等下次用到才真正释放。⚠️ 连接池应用 kill 后会自动重建,治标不治本,必须配合应用侧调整
maximum-pool-size。
7.3 临时上调 processes(需重启)
sql
ALTER SYSTEM SET processes=2500 SCOPE=SPFILE;
-- 重启生效
-- 同步调整 sessions(通常 ≈ 1.5 * processes + 22)
ALTER SYSTEM SET sessions=3800 SCOPE=SPFILE;
还需要配合调整:OS 层
nproc/nofilelimits、PGA_AGGREGATE_TARGET、SGA 大小。
八、service_name 查询注意事项
8.1 大小写敏感
v$session.service_name 按 PMON 注册时的原样存储,精确查不到时用模糊:
sql
SELECT service_name, COUNT(*) cnt
FROM v$session
WHERE UPPER(service_name) LIKE '%CCRB01%'
GROUP BY service_name;
8.2 确认 service 是否存在
sql
-- 监听器里注册的
SELECT name, inst_id, creation_date
FROM gv$active_services
WHERE UPPER(name) LIKE '%CCRB01%';
-- 数据库元数据里配置的
SELECT name, network_name FROM dba_services
WHERE UPPER(name) LIKE '%CCRB01%';
8.3 默认服务 vs 自定义服务
| 类型 | 举例 | 特征 |
|---|---|---|
| 默认服务 | ccrb04、ccrb04.domain、db_unique_name |
PMON 自动注册,无法 srvctl 管理,无角色属性 |
| 自定义服务 | ccrb04_app、ccrb04_ro |
srvctl 创建,可设 -role PRIMARY / -role PHYSICAL_STANDBY |
应用永远不要连默认服务,连自定义的 role-based service,Data Guard 切换才能透明。
九、判断连接池问题的信号
| 观测到的现象 | 大概率原因 |
|---|---|
ACTIVE=0 但 INACTIVE 大量堆积 |
连接池预分配过大(maximum-pool-size / minimum-idle 太大) |
| 同一 machine/Pod 占用 100+ 连接 | 连接池参数设置不合理 |
last_call_et 平均几小时 |
连接长期空闲未回收,idle-timeout 未设或过长 |
logon_time 集中在 Pod 启动时刻 |
minimum-idle 启动即建满 |
多个 XxxBootApplication 共存 |
多个微服务共用一个数据库,需分别排查 |
十、HikariCP 推荐参数(应用侧治本)
yaml
spring:
datasource:
hikari:
maximum-pool-size: 20 # 单 Pod 最大连接,别超 20~30
minimum-idle: 5 # 常驻少量
idle-timeout: 300000 # 5 分钟空闲回收
max-lifetime: 1800000 # 30 分钟强制重建,避免连接老化
connection-timeout: 30000
validation-timeout: 5000
keepalive-time: 150000 # 2.5 分钟心跳
估算数据库 processes 需求:
总连接 ≈ 微服务数 × Pod副本数 × maximum-pool-size + 运维/监控会话 + 后台进程缓冲
HikariCP 官方观点:连接池不是越大越好 。池大小
= (2 × CPU核心) + 有效磁盘数是经验起点,大多数场景 10~20 就够。
十一、主动埋点 module(应用侧)
应用代码里显式设置,使 v$session.module 有业务意义,便于日后排查:
Java (JDBC)
java
Connection conn = ds.getConnection();
conn.setClientInfo("OCSID.MODULE", "OrderService");
conn.setClientInfo("OCSID.ACTION", "createOrder");
PL/SQL
sql
BEGIN
DBMS_APPLICATION_INFO.SET_MODULE('BatchJob', 'NightlyETL');
END;
/
MyBatis 拦截器、Spring AOP 可全局设置 module=服务名、action=方法名。
十二、常用组合命令速查
sql
-- 1. 看水位
SELECT resource_name, current_utilization, max_utilization, limit_value
FROM v$resource_limit WHERE resource_name IN ('processes','sessions');
-- 2. 看 module 分布
SELECT module, COUNT(*) FROM v$session WHERE type='USER' GROUP BY module ORDER BY 2 DESC;
-- 3. 看特定 service 下的应用
SELECT module, machine, COUNT(*) FROM v$session
WHERE type='USER' AND service_name='xxx'
GROUP BY module, machine ORDER BY 3 DESC;
-- 4. 找泄漏
SELECT module, machine, COUNT(*) FROM v$session
WHERE type='USER' AND status='INACTIVE' AND last_call_et>3600
GROUP BY module, machine ORDER BY 3 DESC;
-- 5. 预览 KILL 语句
SELECT 'ALTER SYSTEM KILL SESSION '''||sid||','||serial#||''' IMMEDIATE;'
FROM v$session WHERE <条件>;