ORA-00020: maximum number of processes (500) exceeded 排查与 pfile/spfile 参数调优实战
2026/9/23 21:47:14 网站建设 项目流程

1. 从一次登录失败说起:ORA-00020 到底卡在哪

ORA-00020: maximum number of processes (500) exceeded,这个报错的意思是 Oracle 实例当前允许的最大进程数已经被占满,新的连接请求连认证阶段都进不去。它和「用户名密码错误」「监听没起来」完全不是一类问题——后者至少能连到实例,而 ORA-00020 是连sqlplus / as sysdba都可能被挡在门外,因为 sysdba 登录同样要占用一个进程名额。

我遇到这个报错的场景很典型:一套 BPM 测试系统,平时跑得好好的,某天早上批量任务和人工登录撞在一起,应用端开始大面积报连接失败,DBA 用 sysdba 想进去看看,结果直接吃了一个 ORA-00020。这时候最要命的不是参数本身,而是「你已经进不去了,怎么改参数」。

processes 这个参数控制的是整个实例允许的最大进程数,它不只是给客户端连接用的。后台进程(PMON、SMON、DBWn、LGWR 等)、并行执行从属进程、Job 进程、共享服务器模式下的调度进程,全都从这个池子里扣名额。所以processes=500并不意味着你能开 500 个客户端会话,实际可用连接数要减去几十个后台进程,再减去并行和 Job 的占用。很多系统按「用户数」去估 processes,估出来偏小,就是这个原因。

和它经常一起被提到的还有 open_cursors。open_cursors 限制的是单个会话能同时打开的游标数量,默认常见值是 300。它和 processes 不是一回事:processes 管「能有多少个进程/会话」,open_cursors 管「每个会话内部能开多少游标」。但两者会互相牵连——如果应用有游标泄漏,单个会话把 open_cursors 撑爆,会报 ORA-01000: maximum open cursors exceeded;而如果会话数本身被 processes 卡死,报的就是 ORA-00020。网上很多帖子一看到连接问题就让你调 open_cursors,方向可能是错的,得先分清报错码。

这篇就按完整链路走一遍:先判断到底是 processes 不够还是游标泄漏,再解决「进不去实例」的问题,然后通过 pfile/spfile 把 processes 调上去,最后验证新值生效。全程给可复制的命令,pfile 和 spfile 的互转也会讲清楚,因为这里踩坑最多。

2. 动手前先理清 pfile 与 spfile 的关系

Oracle 的参数文件有两种形态,理解它们是后面所有操作的基础。

pfile 是纯文本初始化参数文件,传统命名像initdjbpm.ora,可以用记事本直接打开改。spfile 是服务器端二进制参数文件,命名像spfiledjbpm.ora,不能手工编辑,只能用alter system set ... scope=spfilecreate spfile from pfile这类命令生成。实例启动时优先找 spfile,找不到才找 pfile。

关键点在于:alter system set能不能用,取决于实例当前是不是用 spfile 启动的。如果实例是用 pfile 启动的,你执行alter system set open_cursors=800 scope=both会直接报 ORA-32001: 已请求写入 SPFILE, 但是没有正在使用的 SPFILE。这就是很多人卡住的地方——想动态改参数,结果发现根本没有 spfile 在用。

所以处理 ORA-00020 时,先确认实例用的是哪种参数文件,再决定改法。判断方法在能连进去的时候很简单:

show parameter spfile;

如果 VALUE 有路径,说明用的是 spfile;如果 VALUE 为空,说明用的是 pfile。但在 ORA-00020 已经发生、连不进去的情况下,你只能从操作系统层面看$ORACLE_HOME/database目录下有没有 spfile 文件,或者回忆当初建库时是不是用了自定义 pfile 路径。

这里给一个决策表,方便对照:

当前状态能否 alter system推荐改法
用 spfile 启动,能连入可以alter system set processes=... scope=spfile后重启
用 spfile 启动,连不进不能用 pfile 临时启动,改完再生成 spfile
用 pfile 启动不能(报 ORA-32001)直接编辑 pfile,重启,再决定是否转 spfile

processes 是静态参数,改了必须重启实例才生效,scope=memoryscope=both对它是无效的,只能scope=spfile然后重启。这一点要提前有心理预期,别指望不重启就扩容。

3. 进不去实例时,用 pfile 临时启动并调大 processes

ORA-00020 最尴尬的就是 sysdba 也连不上。这时候的思路是:不走常规监听连接,用 pfile 指定一个参数文件把实例拉起来,而这个 pfile 里把 processes 临时调大。

第一步,找到或准备一个 pfile。如果原来就有 pfile(比如D:\DJBPM\initdjbpm.ora),直接用它;如果没有,可以从 spfile 反向生成一个:

create pfile='D:\DJBPM\initdjbpm_new.ora' from spfile;

但注意,这条命令需要你先能连进实例。如果完全连不进,就手工写一个最小 pfile,至少包含以下内容:

*.processes=1000 *.open_cursors=800 *.sga_target=1600M *.db_name='djbpm'

第二步,设置环境变量并登录。Windows 下:

set oracle_sid=djbpm sqlplus /nolog

然后以 sysdba 身份连接到空闲例程(注意是「空闲例程」,不是正常实例):

connect sys/你的密码 as sysdba

如果当前实例还占着进程名额导致连不上,先把它关掉再启动:

shutdown abort; startup pfile='D:\DJBPM\initdjbpm.ora';

shutdown abort是强制关闭,生产环境要谨慎,但在已经无法正常连接、需要抢修的场景下是常用手段。启动成功后,确认参数:

show parameter processes; show parameter open_cursors;

第三步,如果确认要长期使用 spfile,就从改好的 pfile 生成 spfile:

create spfile from pfile='D:\DJBPM\initdjbpm.ora';

这里有个高频报错:直接执行create spfile from pfile;不带路径,会报 ORA-01078 和 LRM-00109: could not open parameter file '...\INITDJBPM.ORA'。原因是 Oracle 去默认目录找 pfile 没找到。解决办法就是显式带上 pfile 的完整路径,像上面那样写from pfile='D:\DJBPM\initdjbpm.ora'

生成 spfile 后,下次启动默认就会用 spfile。但要注意,spfile 生成的位置默认在$ORACLE_HOME/database下,命名规则是spfile<SID>.ora。如果你希望实例稳定用这个 spfile,重启时直接startup即可,不用再指定 pfile。

4. 用 spfile 正常调参并验证生效

如果实例还能连进去,或者已经用 spfile 启动,那调参就规范得多。processes 是静态参数,标准做法是:

alter system set processes=1000 scope=spfile;

执行完不会立即生效,需要重启:

shutdown immediate; startup;

重启后验证:

show parameter processes;

预期看到 VALUE 变成 1000。同时把 open_cursors 也一起调了,避免游标问题:

alter system set open_cursors=800 scope=both;

open_cursors 是动态参数,scope=both会同时改内存和 spfile,立即生效,不用重启。这也是它和 processes 的重要区别。

验证连接数是否真的够用,可以查当前进程占用情况:

select count(*) from v$process; select resource_name, current_utilization, max_utilization, limit_value from v$resource_limit where resource_name in ('processes','sessions');

v$resource_limit这张表很实用,max_utilization能告诉你历史峰值用到了多少,limit_value是当前上限。如果 max_utilization 已经贴着 limit_value,说明确实该扩容了。sessions 和 processes 有换算关系,通常 sessions = processes * 1.1 + 5 左右,调 processes 时 sessions 会自动跟着变,一般不用单独设。

改完参数后,建议用应用侧真实连接压一下,确认不再报 ORA-00020。可以开多个 sqlplus 会话模拟并发:

select username, count(*) from v$session group by username;

观察会话数是否稳定在上限之下。

5. 本篇常见报错与排查清单

调 processes 的过程中,几个报错反复出现,这里集中说清楚。

ORA-32001: 已请求写入 SPFILE, 但是没有正在使用的 SPFILE。原因就是实例用 pfile 启动,你却执行了alter system set ... scope=both/spfile。解决:要么改成直接编辑 pfile,要么先create spfile from pfile='完整路径'生成 spfile 再重启。

ORA-01078 加 LRM-00109: could not open parameter file。原因是create spfile from pfile没带路径,Oracle 去默认目录找不到。解决:显式写from pfile='你的完整路径'

ORA-00020 依旧存在,重启后没变化。检查是不是改错了参数文件——比如你改了 pfile,但实例实际用 spfile 启动,重启后读的还是旧 spfile。用show parameter spfile确认当前用的是哪个。

改了 processes 但连接数没明显增加。processes 只是上限,实际可用连接还要看 sessions 和系统资源。另外如果应用存在连接泄漏,进程被占满只是表象,得从应用侧查未关闭的连接。

open_cursors 调了还报 ORA-01000。说明是单个会话游标泄漏,不是全局上限问题,要查应用代码里 ResultSet、Statement 有没有正确关闭,光调参数治标不治本。

排查顺序建议固定成:先看报错码是 ORA-00020 还是 ORA-01000,再看v$resource_limit的 max_utilization,再确认参数文件类型,最后才动手改。顺序错了容易白折腾。

6. 参数调优之后,把验证动作固定下来

processes 和 open_cursors 调完不是终点,得有一套固定的验证动作,避免下次又被动抢修。我一般会在改完后立刻做三件事:查show parameter processes确认新值、查v$resource_limit看 limit_value 是否更新、用应用真实账号连一次确认业务可用。

如果这套库还要长期跑,建议把参数变更记录到变更文档里,写清楚改前值、改后值、重启时间、验证结果。Oracle 的参数问题很多都是「当时改了,过段时间忘了」,下次再出问题又要从头查一遍。

对于需要频繁连数据库做排查、写 SQL、跑脚本的场景,本地工具链也可以顺手配好。我平时会用 TaoToken 这类平台来统一管理模型调用和编码辅助,它的 API 接入方式比较直接,文档在 https://taotoken.net/api ,需要生成 Key 的话在 https://taotoken.net/api-keys 这边操作。做数据库排障时经常要让模型帮忙解释报错、生成排查 SQL,有个稳定的调用入口会省不少事。模型对话入口在 https://taotoken.net/models ,长期写脚本、做 Agent 的话可以看下 Coding Plan:https://taotoken.net/coding-plan 。

回到数据库本身,最后再强调一个容易忽略的点:processes 调大之后,操作系统的进程数限制、内存也要跟着评估。processes 从 500 提到 1000,每个进程都要占内存,SGA 和 PGA 的规划要同步检查,别参数改上去了,系统资源先扛不住。参数调优从来不是改一个数字那么简单,配套资源一起看,才算真正把 ORA-00020 解决干净。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询