sessions_per_user 仅限制用户已认证的并发数据库会话数,非tcp连接或连接池空闲连接;生效前提为resource_limit=true、用户显式绑定profile,且需防范inactive会话残留与连接池耗尽配额。
oracle 没有“用户级并发连接数”这个直接控制项,sessions_per_user 是最接近的机制,但它管的是**已认证的数据库会话数量**,不是 tcp 连接、监听队列或连接池里的空闲连接。
为什么设置了 SESSIONS_PER_USER 却没拦住连接
常见失效不是命令写错,而是几个关键点被跳过:
-
RESOURCE_LIMIT必须为TRUE—— 用SHOW PARAMETER resource_limit查,若为FALSE,执行ALTER SYSTEM SET resource_limit = TRUE SCOPE = BOTH - 用户没显式指定 profile,就走默认的
DEFAULTprofile,而它的SESSIONS_PER_USER是UNLIMITED - 应用用了连接池(如 HikariCP),池里维持了 20 个 idle session,哪怕只发 1 个请求,也会占满配额
- 已有会话不被清理:应用没调
connection.close(),v$session中残留大量STATUS = 'INACTIVE'的会话,新登录直接报ORA-02391
怎么设置并确认 SESSIONS_PER_USER 生效
必须走 profile 赋值路径,不能直接改用户属性:
- 新建 profile:
CREATE PROFILE app_limit LIMIT SESSIONS_PER_USER 8; - 绑定用户:
ALTER USER app_user PROFILE app_limit; - 验证 profile 设置:
SELECT LIMIT FROM DBA_PROFILES WHERE PROFILE = 'APP_LIMIT' AND RESOURCE_NAME = 'SESSIONS_PER_USER'; - 查该用户当前会话数:
SELECT COUNT(*) FROM v$session WHERE USERNAME = 'APP_USER';
注意:修改后立即对新登录生效,但不会踢掉已有会话。
SESSIONS_PER_USER 和其他“连接数”参数的区别
别把它和这些概念混用:
-
PROCESSES(初始化参数):整个实例允许的最大 OS 进程数,影响所有用户总和 -
SESSIONS(推导参数):由PROCESSES计算得出,仍是实例级总量,非单用户 -
LOGICAL_READS_PER_SESSION或CPU_PER_SESSION:限制单个会话的资源消耗,和数量无关 -
ALTER SYSTEM KILL SESSION:手动终止,是事后操作,不是预防性限制
上线前必须验证的真实边界
别只看 SQL*Plus 登六次报错就认为 OK:
- 用同一用户名脚本循环
sqlplus user/pass@db,观察第 N+1 次是否稳定返回ORA-02391 - 检查
v$session中USERNAME和SERVICE_NAME是否一致 —— 某些中间件或 DBLINK 可能导致会话归属判断偏差 - 如果用户通过
ALTER SESSION SET CURRENT_SCHEMA切换 schema,仍计入原用户名的会话总数,无法绕过
最容易被忽略的是:连接池空闲连接、未 close 的 JDBC connection、以及共享服务器模式下调度进程复用带来的监控失真 —— 这些场景下,v$session 数和应用感知的“连接数”永远对不上。











