简介:围绕 Oracle SGA 参数调整引发数据库启动异常的排查与恢复,这份 docx 文档面向具备一定 Oracle 运维基础的 DBA 与系统管理员,聚焦参数误调后实例无法正常启动这一高频故障场景。内容以 Linux 环境下的应急处理为主线,给出三条可落地的恢复路径:用 pfile 直接启动实例、由 pfile 重建 spfile、修改 pfile 中的 SGA 错误参数,并强调调整前备份 dbs 目录与 spfile 的必要性;预览中可看到 startup、create spfile、shutdown immediate、show parameter 等命令的实际执行过程与内存分配输出,便于对照自身故障现象逐步复现。压缩包仅含 1 个 docx 文件,体积约 14KB,轻量易取,适合随查随用。目前已有 328 人学习下载,可作为 Oracle 内存参数调优与启动故障应急的参考材料,帮助读者建立先备份、再验证的排错习惯。
1. 改完 SGA 起不来:那条 ORA-错误背后到底发生了什么
在 Linux 上改完sga_max_size、sga_target,执行shutdown immediate再startup,结果例程直接起不来——这种故障在数据库运维里太常见了,常见到 DBA 半夜被告警叫醒时,十有八九是内存参数被动过。真正折磨人的地方不在于「数据库起不来」,而在于它起不来的时候连一句人话都不给你:错误堆在告警日志里,SQL*Plus 只轻飘飘回一句连接失败。三年没碰过命令行的人、只改过一个数字以为没风险的人、手头没有备份却已经改了参数的人,都是这类问题的高发人群。这篇复盘要解决的,就是从报错现象一路定位到 spfile 出错的根因,再把三种能把库拉起来的办法讲透。
2. 为什么改 SGA 就起不来:spfile 里存的是「硬账本」
2.1 SGA 参数落到 spfile 之后,启动阶段就多了一道硬校验
Oracle 启动大致分三步:nomount 阶段读参数文件、分配 SGA、启动后台进程;mount 阶段加载控制文件;open 阶段打开数据文件和重做日志。SGA 参数是在第一步就被用掉的,也就是说,参数文件里只要有任何一个值超出操作系统或实例能承受的范围,例程连 nomount 都过不去。这跟「性能调优」完全是两码事——调优是在库跑起来之后动,失败了大不了再改回去;启动参数写错,是开局就把门锁死。
常见做法是ALTER SYSTEM SET sga_target=... SCOPE=SPFILE;这条语句本身会成功,因为它只是往 spfile 里写二进制记录,不校验新值到底能不能分配。改动要到下一次startup才真正生效,这就是为什么很多人在改完的那一刻毫无感觉,等到重启(甚至是几个月后的一次计划内重启)才翻车。血泪经验里最扎心的一条就是:改 SGA 一定要重启验证,不要改完就下班。
还有一点容易被忽略:Oracle 对 SGA 的约束是分层校验的。sga_max_size是上限,sga_target不能超过它;sga_target设成 0 表示关闭自动内存管理,这时候各池(db_cache_size、shared_pool_size、large_pool_size、java_pool_size、streams_pool_size等)要各自手填;而memory_target一开,又会反过来接管sga_target和pga_aggregate_target。这几个参数之间的关系是互相咬死的,改了一个不动另一个,就容易出现「参数值本身合法、组合起来不合法」的情况。这种组合错误在 spfile 里不会报错,只在启动分配内存时暴雷。
2.2 报错长什么样:从告警日志里把真话捞出来
数据库起不来时,SQL*Plus 通常只给你:
# 典型的启动失败反馈,信息量极低 SQL> startup ORA-01078: failure in processing system parameters LRM-00109: could not open parameter file '/oracle_install/product/11.2.0/dbs/initorcl.ora'这里的ORA-01078是「处理系统参数失败」的总壳子,真正的原因在下一行。注意LRM-00109说的是找不到参数文件,它和 SGA 参数越界是两类问题,但表现得很像,都是 startup 直接失败。区分办法很直接:看它找的是initorcl.ora(pfile)还是spfileorcl.ora(spfile)。如果提示找不到 pfile,说明实例已经退回去找文本参数文件了,通常是 spfile 已损坏或被改名。
如果是内存参数越界,更常见的形态是:
# 告警日志里的真实错误,比 SQL*Plus 的输出详细得多 ORA-00845: MEMORY_TARGET not supported on this system # 或者 ORA-27102: out of memory Linux-x86_64 Error: 28: No space left on deviceORA-00845几乎只在 Linux 上出现,根因是/dev/shm这个共享内存文件系统空间不够,或者挂载大小没有覆盖memory_target的值。ORA-27102加Error: 28则更直接,是内核层面分配不到内存。这两条报错都指向「值超出了机器当前能给的能力」,而不是值本身写错了。
把真话捞出来的路径是固定的:先去$ORACLE_BASE/diag/rdbms/<db_name>/<sid>/trace/alert_<sid>.log里翻最后一次启动记录。我一般会这么干:
# 找到告警日志的绝对路径,避免在错误的目录里瞎翻 sqlplus -S / as sysdba <<'EOF' SELECT value FROM v$diag_info WHERE name = 'Diag Trace'; EOF # 从告警日志里截取最近一次启动尝试前后的内容 grep -n -A 30 -B 5 "Starting ORACLE instance" \ /oracle_install/diag/rdbms/orcl/orcl/trace/alert_orcl.log | tail -60第一段查诊断目录,参数name = 'Diag Trace'是固定的,别写成Diag Alert,两个路径不同但内容基本一致。第二段用grep定位「Starting ORACLE instance」这个标记行,前后各带一段上下文;-A 30表示往后取 30 行,-B 5往前取 5 行,tail -60防止早期日志太多把最新的一次淹掉。看完这段,是内存越界还是找不到参数文件,基本一眼就能定性。
2.3 版本差异会让同一个参数表现不同
Oracle 10g 之后参数管理有几次明显变化,排查时不能一概而论。10g 起sga_target支持自动共享内存管理;11g 引入memory_target,把 SGA 和 PGA 一起管;12c 之后又做了若干调整,多租户环境下还要区分 CDB 和 PDB 的参数作用域。这意味着同一句ALTER SYSTEM SET sga_target=4G,在 10g 单实例、11g 自动内存管理模式、12c 多租户容器里,落到 spfile 的位置和生效范围都不一样。
具体到排查动作上,有两点差异要留意。第一,memory_target不为 0 时,sga_target和pga_aggregate_target会被自动管理,你手动设sga_target可能被忽略或者直接报 ORA-00838 一类冲突错误;第二,11g 及以上MEMORY_TARGET依赖/dev/shm,而 10g 的sga_target走的是更老的共享内存机制,报错形态完全不同。很多人拿网上搜到的 10g 经验套到 11g 的库上,越改越乱,根子就在这里。
提示:改参数之前先跑一次
SELECT * FROM v$version;和SHOW PARAMETER memory_target;,确认版本和当前所处的内存管理模式,再决定动哪个参数。
3. 三种救火路径:从 pfile 绕行到复原 spfile
3.1 方法一:先用 pfile 启动,再从 pfile 重建 spfile
这是最稳、也最常被推荐的路子。原理很朴素:spfile 是二进制文件,不能直接编辑;而 pfile 是纯文本,$ORACLE_HOME/admin/<SID>/pfile/目录下通常还留着历史生成的文件(命名形如init.ora.8282011115435,后面那串数字是生成时间戳)。只要这个文件里没有那行错误的 SGA 参数,用它启动就能把库拉起来。
-- 用指定的 pfile 启动,绕开损坏或有问题的 spfile SQL> startup pfile='/oracle_install/admin/orcl/pfile/init.ora.8282011115435'; ORACLE instance started. Total System Global Area 612368384 bytes Fixed Size 1250428 bytes Variable Size 167775108 bytes Database Buffers 436207616 bytes Redo Buffers 7135232 bytes Database mounted. Database opened.第一行startup pfile=...里的路径必须写绝对路径,用单引号包住,路径里不能有多余空格。启动成功后输出里的Total System Global Area 612368384 bytes就是本次实际分配的 SGA 总量,这个数字要记住,它和后面重建 spfile 之后的数字会不一样,是判断新 spfile 是否生效的关键依据。如果这个路径下的 pfile 也被改坏了,那就去$ORACLE_HOME/dbs/或者归档目录里找更早的时间戳版本。
库起来之后立刻做重建,不要拖:
-- 用当前验证可用的 pfile 生成一份新的 spfile SQL> CREATE SPFILE FROM PFILE='/oracle_install/admin/orcl/pfile/init.ora.8282011115435'; File created. -- 关闭并重新验证 spfile 是否可用 SQL> SHUTDOWN IMMEDIATE; Database closed. Database dismounted. ORACLE instance shut down. SQL> STARTUP MOUNT;CREATE SPFILE FROM PFILE=这条命令会把文本文件编译成二进制 spfile,写到默认位置$ORACLE_HOME/dbs/spfile<SID>.ora。注意它是覆盖式的,同名文件会被直接替换——这也正是它有用的原因,坏掉的 spfile 被一份健康的替换掉了。SHUTDOWN IMMEDIATE之后立刻STARTUP MOUNT是做验证,mount 成功说明参数文件已经能被正常解析、SGA 能正常分配,此时再ALTER DATABASE OPEN;就是全量验证。
3.2 用 show parameters 确认新 spfile 真的生效了
重建完最忌讳的就是「以为好了」。很多人STARTUP MOUNT成功就收工,结果下次重启又翻车,因为 spfile 的位置可能被SPFILE参数指到了别处,或者环境变量ORACLE_SID跟文件名对不上。验证动作我一般固定跑这几条:
-- 确认当前实例用的是哪个 spfile,以及它的物理路径 SQL> SHOW PARAMETER spfile; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ spfile string /oracle_install/product/11.2.0/dbs/spfileorcl.ora -- 确认 SGA 相关参数的实际值和生效值 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 PARAMETER spfile的VALUE列就是当前实例真正在读的那个文件。如果这一列显示的是?/dbs/spfile@.ora这种带问号的模板形式,或者干脆为空,说明实例跑在 pfile 模式上,你之前的重建其实没被用上——这是高频误会点。SHOW PARAMETER sga里sga_max_size和sga_target两个值应该一致或者后者不大于前者,如果是sga_target大于sga_max_size,那这份 spfile 还是坏的。
顺带补一个参数对照表,改 SGA 时按这个检查组合关系:
| 参数 | 含义 | 常见误配 |
|---|---|---|
sga_max_size | SGA 硬上限,启动时按它预留地址空间 | 设得比物理内存还大 |
sga_target | 自动共享内存管理的目标值 | 大于sga_max_size |
memory_target | SGA+PGA 总上限,非 0 时接管上面两个 | 与/dev/shm大小不匹配 |
db_cache_size等池参数 | 手动管理模式下各池大小 | sga_target非 0 时手填造成冲突 |
这张表的价值在于:改任何一个值之前,先横着看一行、竖着看一列,能挡掉大半的组合错误。尤其是memory_target非 0 的场景,下面几个池参数的手填值会被忽略甚至引发报错,很多人不知道这一点,改完发现「参数没生效」,又去怀疑 spfile 损坏。
3.3 方法二:直接改 pfile 里的错误参数
如果连 pfile 都被改坏了,或者手上只有一份文本参数文件,那就直接编辑它。用vi打开init.ora.8282011115435,把sga_max_size、sga_target、memory_target这几行改回一个保守值,或者直接注释掉。
# 编辑 pfile,把越界的 SGA 参数改小或注释掉 vi /oracle_install/admin/orcl/pfile/init.ora.8282011115435 # 关键行示例:注释掉原来的大值,写一个保守值 # *.sga_target=8589934592 *.sga_max_size=396M *.sga_target=396M*.前缀表示对所有实例生效,单实例环境里写不写都行,但在 RAC 或同主机多实例场景下必须保留,否则参数会作用到错误的实例上。改完保存,再用方法一的startup pfile=走一遍验证。这里有个坑:pfile 里的单位可以用M、G,但如果你写1024M而机器共享内存只有 800M,照样起不来,所以保守值是关键——先让库起来,再按实际内存往上调,比一次调到位安全得多。
改完之后我建议顺手做个 diff,把改动前后的差异留档:
# 留一份改动记录,方便出问题时回滚对比 cp /oracle_install/admin/orcl/pfile/init.ora.8282011115435 \ /oracle_install/admin/orcl/pfile/init.ora.bak.$(date +%Y%m%d) diff /oracle_install/admin/orcl/pfile/init.ora.bak.$(date +%Y%m%d) \ /oracle_install/admin/orcl/pfile/init.ora.8282011115435cp那行用$(date +%Y%m%d)生成带日期的备份名,避免多份备份互相覆盖;diff用来确认只改了预期的那几行,没顺手改坏别的参数。这个习惯看着啰嗦,但在「改完还是起不来」的时候,一份 diff 能直接把排查范围从整份文件缩到两行。
3.4 方法三:提前备份 dbs 目录,出事后覆盖回去
这是纯粹的后悔药路线,逻辑最简单:改参数之前把$ORACLE_HOME/dbs整个目录备份一遍,出问题就把spfile<SID>.ora拷回去。
# 改动前的必备动作:整目录备份 cp -a /oracle_install/product/11.2.0/dbs \ /oracle_install/product/11.2.0/dbs.bak.$(date +%Y%m%d) # 出事后恢复:把健康的 spfile 覆盖回原位 cp -a /oracle_install/product/11.2.0/dbs.bak.20240828/spfileorcl.ora \ /oracle_install/product/11.2.0/dbs/spfileorcl.ora # 确认文件属主和权限没被改坏,否则实例起不来 ls -l /oracle_install/product/11.2.0/dbs/spfileorcl.oracp -a的-a参数是保留权限、属主、时间戳,这一点非常关键:Oracle 的 spfile 必须是 oracle 用户可读、权限一般是 640,如果用普通cp在别的用户下操作,文件属主可能变成 root,实例读取时会报权限错误,反而制造出新故障。最后那行ls -l就是检查这个,看属主是不是 oracle、权限位是不是-rw-r-----。这步很多人省掉,然后对着一个「文件明明在、就是起不来」的现场发呆半天。
三种方法怎么选,我的固定顺序是:先试方法一,因为不动任何文件、可回退;方法一天效再上方法二,改文本文件;方法三只在改动前有备份的前提下才有意义,属于预防而非救火。方法三最容易的误用是「备份做了,但覆盖回去时覆盖错了文件」——$ORACLE_HOME/dbs下可能有initorcl.ora、spfileorcl.ora、orapworcl等多个文件,只覆盖 spfile 才安全,把密码文件或者整个目录盲目覆盖回去,可能引出认证失败的新问题。
4. 避坑清单:这五个坑我踩过,免得你再踩
4.1 改完不重启,等到下次计划内重启才炸
现象:参数调整是几个月前做的,系统一直跑得好好的,某次例行重启突然起不来,现场所有人第一反应都是「最近谁动了什么」。 原因:ALTER SYSTEM SET ... SCOPE=SPFILE只写文件不校验,错误值一直潜伏在 spfile 里,直到下次真正加载才暴露。 解决:任何写 spfile 的改动,做完立刻安排一次可控的重启验证,验证通过才算完成;验证窗口要选业务低峰,别在白天动。
4.2 只改 sga_target 没管 sga_max_size
现象:报错是ORA-02097或ORA-00823一类,提示参数值无效或超出范围。 原因:sga_target被设成超过sga_max_size,两个值互相矛盾,实例在分配阶段就拒绝。 解决:先用SHOW PARAMETER sga看清两个值,改的时候保证sga_target <= sga_max_size;要往上调,先调sga_max_size再调sga_target,顺序反了会当场报错。
4.3 忘了 /dev/shm 这个隐形天花板
现象:Linux 上改了memory_target,重启报ORA-00845: MEMORY_TARGET not supported on this system。 原因:memory_target依赖/dev/shm共享内存文件系统,默认挂载大小往往小于你设的值。 解决:先用df -h /dev/shm看当前容量,再决定memory_target设多大;要调整挂载大小得改/etc/fstab,这属于系统层操作,改完必须重新挂载并验证,不要直接在跑着库的机器上试。
4.4 用 pfile 起来了就以为万事大吉
现象:startup pfile=...成功,库能用了,第二天重启又挂。 原因:实例仍跑在 pfile 模式,spfile 根本没被修复;SHOW PARAMETER spfile的值为空就是证据。 解决:pfile 启动只是临时通道,必须补上CREATE SPFILE FROM PFILE=并重启验证,最后用SHOW PARAMETER spfile确认路径指向真实文件。
4.5 恢复备份时把整个 dbs 目录覆盖回去
现象:spfile 覆盖回去了,库却报认证失败或者密码文件错误。 原因:dbs目录下不止 spfile,还有密码文件orapw<SID>和 pfile 副本,整目录覆盖会把密码文件一起退回到旧版本。 解决:只恢复spfile<SID>.ora这一个文件,恢复后用ls -l确认属主是 oracle、权限是 640;密码文件要不要动,单独判断。
5. 快速定位:三分钟判断问题出在参数文件还是内存
现场排查时我不会一上来就翻日志,而是按一个固定顺序快速缩小范围,这套顺序能挡掉八成情况。
第一步,看 startup 的第一行报错,把ORA-编号抄下来。ORA-01078加LRM-前缀基本锁定参数文件问题;ORA-00845、ORA-27102锁定内存分配问题;单纯ORA-01034是实例没起,属于结果不是原因。
第二步,确认实例到底在找哪个参数文件。
# 从环境变量和文件系统两侧对照,判断 spfile 是否存在 echo $ORACLE_SID ls -l $ORACLE_HOME/dbs/spfile*.ora $ORACLE_HOME/dbs/init*.ora 2>/dev/null如果spfile<SID>.ora不存在而init<SID>.ora存在,实例会退回 pfile 模式;两个都不存在,就是LRM-00109。这一步能立刻区分「文件丢了」和「文件坏了」。
第三步,用 pfile 隔离变量。拿一份历史 pfile 执行startup pfile=,能起来就证明是 spfile 内容问题,起不来就往内存和系统层查。这一步是整个排查的分水岭,几乎所有分支都从这里分开。
第四步,核参数组合。把SHOW PARAMETER sga、SHOW PARAMETER memory_target、df -h /dev/shm三条输出并排看,对照前面那张参数表,重点看三组关系:sga_target是否超过sga_max_size、memory_target是否超过/dev/shm、memory_target非 0 时是否还手填了各池大小。
| 报错特征 | 高概率根因 | 首个验证动作 |
|---|---|---|
ORA-01078+LRM-00109 | 参数文件缺失或路径不对 | ls -l $ORACLE_HOME/dbs/ |
ORA-00845 | /dev/shm小于memory_target | df -h /dev/shm |
ORA-27102+Error: 28 | 内核内存不足 | 核对 SGA 总和与物理内存 |
ORA-02097/ORA-00823 | 参数组合越界 | SHOW PARAMETER sga |
| 重启后莫名起不来 | spfile 里潜伏错误值 | pfile 启动做隔离测试 |
第五步,留证据再动手。改动前把alert_<sid>.log的最后一次启动片段、当前参数输出、dbs目录清单各存一份,文件名带时间戳。这套动作的目的是:万一第一次修复没成,至少还能对比出「修之前是什么状态」,不至于在两次失败之后连现场都还原不了。
从那以后我每次改 SGA 参数,都会强制走一遍「备份 dbs 目录、SCOPE=SPFILE 改值、立刻重启验证、SHOW PARAMETER 复核」这四步,一步不省——不是因为我记不住命令,而是因为这类故障最贵的地方从来不是修,是修之前的几个小时翻日志和猜。希望帮到你。
本文还有配套的精品资源,点击获取