SESSIONS_PER_USER 是 Oracle PROFILE 中限制同一用户同时数据库会话数的参数,仅对认证成功后的活跃或未断开会话生效,不控制TCP连接、监听器队列或连接池空闲连接。
SESSIONS_PER_USER 是什么,它真能限制并发连接数?
sessions_per_user 是 oracle 数据库 profile 中的一个参数,但它只控制「同一用户在同一时刻能建立的**会话数**」,不是操作系统级或网络层的并发连接限制。关键点在于:它只在用户成功认证后、会话真正创建时才生效;tcp 连接建立、登录过程中的握手、甚至密码错误重试,都不受它约束。
常见错误现象:ORA-02391: exceeded simultaneous sessions per user limit —— 这个报错出现时,说明用户已通过认证,且当前活跃会话(v$session 中 STATUS = 'ACTIVE' 或 'INACTIVE' 但未断开)已达上限。
- 它不阻止客户端发起新 TCP 连接(比如用 sqlplus 反复敲回车重连)
- 它不干预数据库监听器(
lsnrctl)的连接队列或MAX_PROCESSES限制 - 如果应用使用连接池(如 UCP、HikariCP),一个池可能维持几十个空闲会话,
SESSIONS_PER_USER很快被耗尽
怎么设置和验证 SESSIONS_PER_USER 生效?
必须先创建或修改 PROFILE,再将该 profile 赋给用户。直接改用户参数无效。
实操建议:
- 新建 profile:
CREATE PROFILE app_user_prof LIMIT SESSIONS_PER_USER 5; - 赋给用户:
ALTER USER app_user PROFILE app_user_prof; - 立即生效,无需重启实例;但已有会话不受影响(只约束新登录)
- 验证是否生效:
SELECT LIMIT FROM DBA_PROFILES WHERE PROFILE = 'APP_USER_PROF' AND RESOURCE_NAME = 'SESSIONS_PER_USER'; - 查当前用户会话数:
SELECT COUNT(*) FROM v$session WHERE USERNAME = 'APP_USER';
为什么设了还是拦不住“大量连接”?常见漏点
根本原因:SESSIONS_PER_USER 的粒度是「数据库会话」,而真实场景里,“连接”常被混淆为网络连接、应用连接池连接、中间件连接、甚至短连接脚本。
- 应用没正确关闭连接(没调
connection.close()),导致v$session中残留大量INACTIVE会话,很快占满配额 - Oracle 默认 profile(
DEFAULT)的SESSIONS_PER_USER值是UNLIMITED,若用户没显式指定 profile,就走默认值 - DBA 误以为设置了
SESSIONS_PER_USER就等于限了监听连接数,结果lsnrctl status显示连接堆积,但查v$session却没几个会话 —— 实际是卡在认证前 - 使用共享服务器模式(Shared Server)时,一个调度进程(
D000)可服务多个用户会话,SESSIONS_PER_USER仍按用户计,但底层连接复用会让监控更难对齐
真要控并发,该看哪些地方?
如果目标是防止数据库被突发连接打垮,SESSIONS_PER_USER 只是拼图一角。必须分层看:
- 监听器层:调整
listener.ora中CONNECT_TIMEOUT_LISTENER和MAX_CONNECTIONS(12c+),或用tcp.validnode_checking配合tcp.invited_nodes控制来源 - 实例层:
PROCESSES参数硬性限制总进程数(含后台进程),超限直接报ORA-00020: maximum number of processes (%s) exceeded - 应用层:强制连接池配置最大活跃连接(
maxPoolSize)、空闲连接回收(idleTimeout)、连接泄漏检测 - 监控兜底:用
DBA_USERS的PROFILE字段 +v$session实时聚合,写脚本定期告警异常增长
最易被忽略的是:profile 修改后,旧会话不退出,新连接又进不来,用户感知是“突然连不上”,但 DBA 查 v$session 发现会话数远低于 SESSIONS_PER_USER —— 其实是这些会话卡在 INACTIVE 状态太久,没被应用主动释放,也没被数据库 SQLNET.EXPIRE_TIME 扫描到。

















