简介:面向 Oracle 数据库运维人员与初学者的实战排错文档,专门讲解调整 SGA(系统全局区)参数后实例无法启动这类高频故障。内容围绕故障定位与恢复展开:先用 Linux 应急启动方式指定 pfile 启动实例,验证启动成功后判断为 spfile 损坏,再由 pfile 反向生成 spfile 并重启确认;同时给出两条备选路径,一是直接修改 pfile 中 sga_max_size、sga_target 等错误参数,二是改动前备份 dbs 目录、异常时用 spfileSID.ora 回滚,并提醒调整前先备份、调整后验证启动与性能。压缩包为 1 个 docx 文件,约 14KB,命令与说明混排,便于对照执行、随查随用。已有 328 人学习下载,适合需要快速恢复生产库、补齐 SGA 参数管理思路的读者参考。
1. 改完 SGA 起不来:ORA-27102 这类启动异常到底卡在哪
改完sga_max_size或sga_target之后执行startup,报出 ORA-27102: out of memory 或者干脆没有任何明细就停住,随后浏览器里开始搜「oracle改sga异常」,这是 DBA 值班里相当高频的一类故障。麻烦在于它常常出现在一个很尴尬的时刻——参数刚改完、库刚重启,业务连接全部堆积,监控在报连接数打满,人还得在几分钟内决定是回退参数还是救实例。适合看这篇的人很明确:手上有 Linux 上的单实例库、能登服务器、会用 sqlplus/ as sysdba,但被 SPFILE 这个黑匣子挡在门外的开发和运维。下面从报错现象一路推到根因、再到三种能照抄的恢复路径,最后给一套快速定位的习惯。
2. SPFILE 二进制被写坏:为什么 startup 一定失败而 pfile 能拉起
2.1 现象:startup 报内存分配失败,换 pfile 立刻正常
先把现象摆清。改完 SGA 相关参数,startup的输出通常停在例程启动阶段,报错大致是这几类:ORA-27102: out of memory、ORA-00821: Specified value of sga_target is too small,或者 ORA-00824: cannot set sga_target due to existing internal settings。也有更隐蔽的一种,命令敲下去没有任何报错,直接回到SQL>提示符,show parameter sga一看,值根本没生效。
这时候最值钱的一步动作是:用带pfile参数的方式启动一次。原文给的应急命令就是这一条,我把它完整写出来,路径按自己的安装目录替换:
# 以 sysdba 身份进入,不做任何参数改动,先用 pfile 硬拉一次 sqlplus / as sysdba SQL> startup pfile='/oracle_install/admin/SID/pfile/init.ora.8282011115435' ORACLE 例程已经启动。 Total System Global Area 612368384 bytes Fixed Size 1250428 bytes Variable Size 167775108 bytes Database Buffers 436207616 bytes Redo Buffers 7135232 bytes 数据库装载完毕。 数据库已经打开。这段输出信息量很大。第一,例程能起来,说明内存本身够、内核参数没被顶穿、Oracle 二进制没问题;第二,SGA 实际分配到了 612368384 字节,接近 584M,而后面恢复完再看show parameter sga,sga_max_size只有 396M——两者对不上,正好说明 pfile 里写的值和 spfile 里被写坏的值不是一回事。第三,数据库能 open,说明控制文件、数据文件、redo 都没事,故障面被压缩到了参数文件这一个点上。
这一步的价值在于切分故障域。同样是「起不来」,可能是内存不足、可能是控制文件损坏、可能是归档空间打满,用 pfile 试一次就能把它们区分开:pfile 起来 = 参数文件问题,pfile 也起不来 = 别在参数文件上耗时间,去看 alert 日志和操作系统层面。
2.2 根因:SPFILE 是二进制,写坏一次就再也读不动
根因要说透。SPFILE 是二进制文件,由数据库实例自己维护,不能手工编辑。改 SGA 参数时常见两种翻车方式:一是在 SGA 已经分配的情况下用ALTER SYSTEM SET改了一个超出物理内存或超出内核限制的值,并且带了SCOPE=SPFILE,于是这个错误值被持久化进 SPFILE,下次启动直接读它,读到的就是个不可能满足的申请量;二是参数之间存在约束关系,比如sga_target不能超过sga_max_size,sga_max_size又受memory_target、hugepage、/dev/shm大小制约,只改其中一个就会触发 ORA-00821、ORA-00824 这类一致性校验报错。
还有一种更阴的情况:SPFILE 文件本身在磁盘层面被写坏,或者被误删、被覆盖成了一个内容不完整的文件。此时实例启动时读取参数失败,报错往往非常含糊,甚至只给一个 ORA-01078: failure in processing system parameters 加 LRM-00109,看不出和 SGA 有关系,容易被误判成整个库崩了。
而 pfile 是纯文本,格式简单,一行一个参数=值,数据库逐行解析,容错性天然比二进制强。所以「pfile 能起、spfile 起不来」这个组合,本质上不是玄学,是文件格式和维护方式决定的:pfile 是你可控的文本,spfile 是实例自己管的二进制黑匣子。
提示:不要试图用文本编辑器直接打开 SPFILE 改内容。看到乱码不是文件坏了,是它本来就不该被手工编辑。
2.3 方法一:用 pfile 反向重建 spfile,一次修好
这是最干净的一条路。既然 pfile 能正常启动,就说明 pfile 里的参数组合是可用的,那么用它反向生成一个新的 SPFILE,SPFILE 里被写坏的值就被整体替换掉了。原文的操作序列照抄如下,我只补注释:
-- 前提:当前实例已用 pfile 成功启动并处于 open 状态 SQL> create spfile from pfile='/oracle_install/admin/SID/pfile/init.ora.8282011115435'; 文件已创建。 -- 关库,让实例下次启动时走默认的 spfile 路径 SQL> shutdown immediate; 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 -- 用默认方式启动,验证 spfile 已恢复正常 SQL> startup mount; ORACLE 例程已经启动。 Total System Global Area 415236096 bytes Fixed Size 1249296 bytes Variable Size 121638896 bytes Database Buffers 285212672 bytes Redo Buffers 7135232 bytes 数据库装载完毕。几个参数必须说清楚。create spfile from pfile=...里的路径指向那个文本参数文件,等号两边不要留空格,路径要用单引号包住。生成的目标位置由数据库的默认规则决定,落在$ORACLE_HOME/dbs下,文件名是spfileSID.ora,这个位置不能随便改,因为实例启动时按固定顺序找参数文件:先找spfileSID.ora,再找spfile.ora,最后才找initSID.ora。这也是为什么重建完必须shutdown再startup,只有重新走一遍启动流程,实例才会去读新的 SPFILE。
startup mount里 SGA 变成 415236096 字节,比原来 pfile 启动时的 612368384 小了一截,这不是出错,是新的 SPFILE 里sga_max_size是 396M 左右,实例按它分配。接着验证两件事,这也是判断修复是否成功的关键:
SQL> show parameters spfile; NAME TYPE VALUE ----------- ----------- ------------------------------ spfile string /oracle_install/product/dbs/spfileORCL.ora SQL> show parameter sga; NAME TYPE VALUE ----------------- ------------ ------------------------------ lock_sga boolean FALSE pre_page_sga boolean FALSE sga_max_size big integer 396M sga_target big integer 396Mshow parameters spfile的 VALUE 不再是空,说明实例确实是从 SPFILE 启动的,这一步排除了「还在用 pfile」的假修复。sga_max_size和sga_target都回到 396M,说明生效的是我们重建后的值。确认无误再alter database open,不要图快直接startup,mount阶段先把参数看一遍,出问题还能原地再改。
注意:重建之前先确认
$ORACLE_HOME/dbs下没有别的实例在用同名 spfile,多实例机器上路径写错会直接影响另一个库。
2.4 方法二:直接改 pfile 里的 SGA 参数再重建
如果 pfile 本身就是「错误参数」的来源——比如应急时随手拷了一份旧 pfile,里面的sga_max_size和物理内存不匹配——那就先把 pfile 改对,再走重建。操作就是编辑那个文本文件:
# 备份再改,别在原文件上直接动手 cp /oracle_install/admin/SID/pfile/init.ora.8282011115435 \ /oracle_install/admin/SID/pfile/init.ora.8282011115435.bak # 编辑时只动 SGA 相关的两三行,其余保持原样 # *.sga_max_size=396M # *.sga_target=396M改完用 pfile 启动验证一次,能起来再执行create spfile from pfile=...。这里最容易踩的坑是只改sga_target不改sga_max_size,或者反过来。这两个参数的关系是:sga_max_size是上限,sga_target是自动管理的目标值,后者不能大于前者;在启用自动内存管理(AMM)的库上,还要受memory_target约束。参数之间是一组约束,不是一个孤立数字,改一个必须回头看另外几个。
改参数时还要考虑操作系统的天花板。SGA 走的是共享内存段,Linux 上可以用ipcs -m看当前共享内存段的总量,用free -m看可用内存,用df -h /dev/shm看共享文件系统剩余空间(AMM 模式下 SGA 会占用/dev/shm)。这三个数任何一个不够,参数写得再对也起不来,报的还是 ORA-27102,症状和 SPFILE 写坏一模一样,但根因完全不同。
3. 三种恢复路径怎么选:备份、重建与回滚的取舍
3.1 方法三:改参数前先备份 dbs 目录,把后悔药提前吃
原文提的第三种办法,本质是把恢复动作前置。做法很朴素:动 SGA 参数之前,先把$ORACLE_HOME/dbs整个目录备份一份,出问题时把spfileSID.ora拷回去,再启动就正常了。
# 改参数前的标准动作:整目录留档,带时间戳方便回滚 cd $ORACLE_HOME tar -czf /backup/dbs_$(date +%Y%m%d_%H%M).tar.gz dbs/ # 出问题后,先停实例,再恢复参数文件 sqlplus / as sysdba SQL> shutdown abort; # 恢复时只回拷 spfile,不要整目录覆盖,避免带进旧的口令文件 cp /backup/dbs_20240101_1030/spfileORCL.ora $ORACLE_HOME/dbs/spfileORCL.ora SQL> startup这个方法的优点是快,几分钟内回到改之前的状态,适合生产库抢时间。缺点是它只能回滚,不能往前修——如果业务确实需要更大的 SGA,回滚只是把问题推迟到下一次改动。另外注意别把整个dbs目录无脑覆盖回去,那里头还有口令文件orapwSID和initSID.ora,覆盖口令文件可能导致远程登录方式变化,凭空多出一个故障。
3.2 三种方法对照:什么时候用哪一个
选哪条路,取决于当前库的状态和你手上有多少信息。我按实际处置顺序整理成一张表:
| 场景 | 首选方法 | 判断依据 | 风险点 |
|---|---|---|---|
| SPFILE 参数值写坏,pfile 可用 | 方法一:pfile 重建 spfile | pfile 能 startup 并 open | 重建后 SGA 变小,需复核性能 |
| pfile 本身参数就错 | 方法二:改 pfile 再重建 | pfile 启动报 ORA-00821/00824 | 参数间约束多,改一个要连带看 |
| 生产库抢时间,改动需回退 | 方法三:恢复 dbs 备份 | 有改动前备份且版本一致 | 只回滚不前进,问题会复现 |
| pfile 和 spfile 都起不来 | 以上都不适用 | alert 日志有非参数类报错 | 故障在内存/存储层,别耗在参数上 |
表格里最后一行值得单独强调。如果拿 pfile 启动同样失败,而且报错不是参数一致性类,而是 ORA-27102 配着操作系统层面的信息,那就要怀疑内存真不够、hugepage 配置变了、/dev/shm被别的进程占满。这时候反复重建 spfile 是无效劳动,正确的动作是看 alert 日志里例程启动那几行,再对照free -m、ipcs -m、df -h /dev/shm的实际数值。
3.3 避坑记录:五次真实翻车换来的注意点
现象一:create spfile from pfile报 ORA-01078 或文件找不到。原因多半是当前实例还在用 pfile 运行,但路径写错、单引号用了中文符号,或者等号两边多了空格。解决是把路径原样复制出来核对,ls -l确认文件存在且 oracle 用户可读,重新执行。
现象二:重建成功,重启后 SGA 变小,业务开始报性能问题。原因是 pfile 是早期备份,里面的sga_max_size比故障前的实际值小。解决是在重建前先show parameter sga记录当前值,或者明确接受变小并从业务侧观察,不要默认「能起来就等于修好了」。
现象三:shutdown immediate卡住很久不返回。原因是有活动会话或大的未提交事务。解决是等一下,确实卡死再用shutdown abort,之后实例恢复会多花点时间,但比一直挂着强;恢复前先确认没有正在跑的批处理作业。
现象四:回拷 spfile 后startup报权限错误。原因是cp用了 root,文件属主变成 root,oracle 用户读不了。解决是回拷后chown oracle:oinstall spfileORCL.ora并确认权限 640,这一步很容易被忽略。
现象五:改了参数没重启,以为已经生效。原因是ALTER SYSTEM SET ... SCOPE=SPFILE只写文件不立即生效,SCOPE=MEMORY只改内存不写文件,重启后打回原形。解决是明确每次改动的 SCOPE,改完用show parameter确认内存中的值,需要持久化就带SCOPE=BOTH,然后安排重启窗口验证。
4. 快速定位:三分钟判断是不是参数文件在搞鬼
出问题时最怕的是乱试。我现在的固定顺序是这样,基本三分钟内能定性。
第一步,不进数据库,先看 alert 日志尾部。$ORACLE_BASE/diag/rdbms/<dbname>/<sid>/trace/alert_<sid>.log,启动失败的那几行一定在里面,ORA-27102、ORA-00821、ORA-01078 分得很清楚,比在客户端猜快得多:
# 只看最近 50 行,重点找 ORA- 开头的行 tail -n 50 $ORACLE_BASE/diag/rdbms/orcl/orcl/trace/alert_orcl.log | grep -E "ORA-|Errors"第二步,用 pfile 试启动,这一步是分水岭。能起来就锁定参数文件,起不来就往内存和存储层查。
第三步,起来了就立刻show parameter sga,把sga_max_size、sga_target、memory_target、lock_sga、pre_page_sga五个值记下来,和改动前的记录对照。这五个值基本能解释绝大多数 SGA 相关的启动异常。
第四步,如果决定重建,验收标准是三条:show parameters spfile有值、show parameter sga数值符合预期、alter database open之后业务连接能正常建立。三条缺一条都不算修完。
第五步,把这次的参数改动、报错原文、恢复动作记进变更记录。血泪经验是,同一个库半年内因为同一个sga_max_size翻两次车的情况并不少见,第二次能省下至少半小时。
我现在的习惯是,任何一次改 SGA 参数,哪怕是测试库,都强制走一遍「备份 dbs 目录 → 记录当前参数值 → 改 → 重启验证 → 复核 show parameter」这五步,一步不跳。那次半夜被电话叫起来、盯着一个二进制文件无从下手的经历,让我再也不敢省这几分钟。希望帮到你。
本文还有配套的精品资源,点击获取