CPU_PER_SESSION是Oracle数据库中一个容易被忽视但非常实用的资源限制参数。它隶属于PROFILE(配置文件)体系,作用是限制单个会话在一次生命周期内累计可以使用的CPU时间总量。当某个会话消耗的CPU时间达到这个上限时,Oracle会终止该会话正在执行的语句,并返回ORA-02392错误,提示超出CPU使用限制。这个机制对于防止个别失控的会话长时间霸占CPU资源、拖慢整个数据库实例具有重要意义。

CPU_PER_SESSION的工作原理与计量单位
要正确使用CPU_PER_SESSION,首先需要理解它的计量方式。该参数的单位是百分之一秒,也就是说,如果你把CPU_PER_SESSION设置为1000,那么单个会话累计可以使用的CPU时间就是10秒。这里的累计指的是会话从建立到结束整个过程中所有SQL语句消耗CPU时间的总和,而不是单条语句的执行时间。如果一个会话执行了一百条小查询,每条消耗0.1秒CPU,累计起来就是10秒,同样会触发限制。
需要特别注意的是,这个统计的是CPU时间而非墙上时间。一条SQL语句可能执行了5分钟,但大部分时间在等待I/O,实际消耗的CPU可能只有3秒。CPU_PER_SESSION只统计那3秒的CPU消耗,等待时间并不计入。这使得它区别于IDLE_TIME和CONNECT_TIME这类基于时间的限制参数,二者经常被混淆。IDLE_TIME限制的是会话空闲的时长,CONNECT_TIME限制的是会话总连接时长,而CPU_PER_SESSION只关心实实在在的CPU计算开销。
当会话的CPU累计消耗达到上限时,Oracle并不会直接杀掉会话连接,而是中断当前语句的执行并回滚该语句。用户会收到类似ORA-02392: exceeded CPU_PER_SESSION的错误。此时会话本身仍然存在,用户可以提交COMMIT或回滚ROLLBACK,但如果继续执行新语句,仍会立即被拒绝,直到会话结束重新连接。这种设计的意图是在保护系统资源的同时,尽量给用户一个体面收尾的机会。
创建PROFILE并应用限制的完整操作
CPU_PER_SESSION不能直接设置在某个会话上,必须通过PROFILE间接实现。PROFILE是Oracle提供的一组资源限制集合,可以分配给多个用户共享。下面演示完整的配置过程。
-- 查看当前系统默认的PROFILE SELECT profile, resource_name, limit FROM dba_profiles WHERE resource_name = 'CPU_PER_SESSION'; -- 创建一个限制会话CPU为30秒(3000百分之一秒)的PROFILE CREATE PROFILE app_user_profile LIMIT CPU_PER_SESSION 3000 SESSIONS_PER_USER 5 CONNECT_TIME 480 IDLE_TIME 60; -- 将PROFILE分配给指定用户 ALTER USER scott PROFILE app_user_profile; -- 使资源限制生效(针对传统方式) ALTER SYSTEM SET resource_limit = TRUE;
这里有一个非常关键的点:RESOURCE_LIMIT初始化参数必须设置为TRUE,否则密码相关的限制(如FAILED_LOGIN_ATTEMPTS)虽然生效,但CPU_PER_SESSION这类资源限制不会真正执行。很多DBA配置了PROFILE却发现限制不生效,排查半天,最后发现就是漏掉了这一步。需要注意的是,如果使用的是基于参数文件的启动方式,还应将resource_limit=TRUE写入spfile以保证重启后仍然生效。
验证限制是否生效可以使用如下查询,观察用户的RESOURCE消耗情况:
-- 查看PROFILE中的CPU限制配置
SELECT resource_name, limit
FROM dba_profiles
WHERE profile = 'APP_USER_PROFILE';
-- 查看会话累计消耗的CPU时间(单位:百分之一秒)
SELECT sid, serial#, username,
statistic#, value
FROM v$sesstat
WHERE statistic# = (SELECT statistic# FROM v$statname
WHERE name = 'CPU used by this session')
ORDER BY value DESC;
-- 查看用户的PROFILE分配情况
SELECT username, profile FROM dba_users WHERE username = 'SCOTT';
通过对比v$sesstat中的CPU消耗值和PROFILE设定的上限,可以提前发现哪些会话即将触碰红线,做到心中有数。
设置多少合适以及常见误区
CPU_PER_SESSION设置成多少并没有标准答案,需要结合业务特征来定。对于OLTP系统中的普通应用用户,单次会话通常执行大量短小的查询,累计CPU消耗一般不会超过几十秒,设置3000到10000(即30秒到100秒)通常比较安全。而对于跑批、报表类用户,一次会话可能执行复杂的聚合运算,CPU消耗以分钟计,设置过小会导致正常业务频繁中断,反而制造故障。
一个常见的误区是把所有用户都套用DEFAULT PROFILE并设置为UNLIMITED。DEFAULT PROFILE默认情况下所有资源限制都是UNLIMITED,这意味着任何会话理论上可以无限消耗CPU。一旦应用代码出现死循环、笛卡尔积查询或缺失索引导致的低效执行计划,单个会话就可能把整个实例的CPU吃满,影响所有用户。在生产环境中,建议至少为不同类型的用户创建分级PROFILE,例如前台应用用户一套、报表用户一套、运维人员一套,各自设置不同量级的限制。
另一个误区是认为CPU_PER_SESSION能精确控制系统负载。实际上它限制的是单会话累计消耗,无法限制瞬时CPU占用率,一个会话可以在几秒内耗尽30秒的CPU额度。如果需要更精细的CPU资源隔离,应该考虑使用Resource Manager(资源管理器),通过CPU_QUOTA等指令按消费者组分配CPU比例,两者配合使用效果更好。此外,PROFILE的修改只对新建会话完全生效,已存在的会话需要重新连接后才会应用新的限制值,这在调整参数时容易被忽略。
小结
CPU_PER_SESSION是Oracle资源管控体系中的第一道防线,它以会话为粒度限制累计CPU消耗,实现简单、开销低,适合快速封堵失控会话。使用时牢记三点:单位是百分之一秒,需要设置RESOURCE_LIMIT为TRUE才生效,修改后要重新连接会话。在更复杂的场景下,把它与CONNECT_TIME、IDLE_TIME以及Resource Manager结合使用,可以构建出分层的数据库资源保护体系,让有限的CPU资源始终服务于最重要的业务。
Oracle数据库CPU_PER_SESSION资源限制修改时间:2026-08-31 03:42:35