资讯详情

资讯详情

Oracle改SGA起不来:pfile应急恢复与spfile重建

简介面向 Oracle 数据库运维人员与 DBA 的故障处理文档聚焦调整 SGA 参数后实例无法启动这一典型场景梳理从定位根因到恢复实例的完整思路。压缩包内仅含 1 个 docx 文件约 14KB篇幅精炼以命令行实录形式呈现启动报错、应急启动与参数校验的关键片段。内容围绕三条处置路径展开用 PFILE 应急启动并以 pfile 重建 spfile、直接修正 PFILE 中的 SGA 参数错误、以及改动前备份 dbs 目录下的 spfileSID.ora 以便回滚同时给出 sga_max_size、sga_target 取值为 396M、lock_sga 等参数的查看结果说明如何判断 spfile 是否异常。适合初中级运维人员对照排查也可作为参数变更前的检查清单参考。已有 328 人学习下载。1. 改完 SGA 起不来这件事比想象中常见上周又碰到一次一台跑了两年多的 Oracle 测试库同事为了缓解内存压力把sga_max_size从 396M 调到 612Malter system set加scopespfile敲完shutdown immediate一切正常再startup就卡住了——例程直接报错退出连 mount 都到不了。这种场面在 Linux 上跑的 Oracle 单实例环境里几乎年年遇到尤其是开发库、测试库这种没人严格按变更流程走的地方改个 SGA 参数随手就来改完不验证 spfile 是否可读重启才发现数据库起不来。更麻烦的是很多人这时候第一反应是去改spfileSID.ora但那是二进制文件vi打开一片乱码越改越糟。其实只要$ORACLE_HOME/admin/SID/pfile/目录下还留着当初建库时生成的init.ora.xxx文本参数文件这条路就没有断。这篇记录的就是我处理「oracle 改 sga 异常」的完整过程怎么用 pfile 应急拉起、怎么从 pfile 反向重建 spfile、怎么改参数、以及以后怎么避免再翻车。适合手上管着 Oracle 单实例、被 SGA 参数坑过一次或即将要调 SGA 的开发者。2. 环境先列清楚Oracle 单实例的 pfile 与 spfile 位置动手之前得先把这套环境的文件布局弄清楚否则后面每条命令的路径都得靠猜。「改 SGA 起不来」这类问题九成不是 Oracle 本身坏了而是启动时读到的参数文件内容不对所以第一件事是确认实例到底在读哪个文件。2.1 两个参数文件的角色分工Oracle 启动时按顺序找参数文件先找spfileSID.ora找不到才退回到initSID.ora。spfile 是二进制、只能通过ALTER SYSTEM或CREATE SPFILE修改优点是集中管理、支持scopememory|spfile|bothpfile 是纯文本可以直接用编辑器改但改了必须重启才生效。两者可以互相转换命令就两条CREATE SPFILE FROM PFILE...和CREATE PFILE FROM SPFILE...。关键点在于改 SGA 出问题坏的一定是 spfile因为scopespfile写的就是它而 pfile 通常是建库那一刻留下的快照内容还是当时那套参数不受后续ALTER SYSTEM影响。这就是应急时 pfile 能救场的原因——它是一份没被污染的历史参数。我一般把 pfile 当作 spfile 的「后悔药」只要那个init.ora.数字串文件还在最坏情况也就是退回到建库时的 SGA 配置。2.2 定位 pfile、spfile 和告警日志先确认环境变量的指向避免在错误的$ORACLE_HOME下操作# 切到 oracle 用户确认关键环境变量 su - oracle echo $ORACLE_HOME # 例如 /u01/app/oracle/product/11.2.0/dbhome_1 echo $ORACLE_SID # 例如 orcl echo $ORACLE_BASE # 例如 /u01/app/oracle这三个变量必须和出问题的实例一致。多实例机器上ORACLE_SID写错会连到另一个正常实例上去白折腾半天还以为问题自己好了。接着按目录找文件pfile 和 spfile 的标准位置是# pfile 存放目录建库时自动生成的文本参数文件 ls -l $ORACLE_HOME/admin/$ORACLE_SID/pfile/ # spfile 存放目录二进制参数文件 ls -l $ORACLE_HOME/dbs/spfile${ORACLE_SID}.ora我这次的现场是 pfile 在oracle_install/admin/SID/pfile/init.ora.8282011115435spfile 在oracle_install/product/dbs/spfileSID.ora。文件名尾巴那串数字是建库时间戳不用管它重点是有没有这个文件、时间戳是不是建库那天的。如果 pfile 目录是空的说明建库时被清过或者从来没生成那就只能走后面 4.x 的备份恢复路线。顺手把告警日志的位置也记下来从 11g 起它在$ORACLE_BASE/diag/rdbms/db_name/sid/trace/alert_sid.log启动失败的真正原因都写在这里面比屏幕上那句 ORA- 错误信息详细得多。这是排查的第一个黑匣子。2.3 版本差异对操作的影响不同版本在参数文件上的行为差别不小照抄网上的命令前先对一下自己的版本版本spfile 默认位置关键差异10g$ORACLE_HOME/dbspfile 与 spfile 机制已成熟scope参数生效11g$ORACLE_HOME/dbs引入 ADR告警日志迁到diag目录排错入口变了12c 及以上$ORACLE_HOME/dbs支持 PDB改 SGA 必须在 CDB 根容器下做12c 之后有个容易踩的点如果连的是 PDBALTER SYSTEM SET sga_target会直接报错SGA 是实例级参数只能在 CDB 里改。另外 11g 之后自动内存管理AMM默认开启memory_target和sga_target同时设置会互相打架启动时报 ORA-00838 之类的错误这也是「改完 SGA 起不来」的常见变体——不是 spfile 损坏是参数组合本身矛盾。提示动手前先执行一次sqlplus / as sysdba做show parameter spfile和show parameter pfile把当前的参数文件路径记录下来。此时如果库是开着的这个信息就是唯一的现场快照。3. 应急启动用 pfile 先把库拉起来库起不来的时候业务侧的压力是实时的优先级永远是先让它跑起来再谈修参数。这一章的三步是连着的先用 pfile 启动验证「spfile 确实是坏的」再从 pfile 重建 spfile最后正常重启确认恢复。3.1 用 startup pfile 绕过 spfile关键命令就一句把 pfile 的完整路径塞给startup-- 以 sysdba 身份登录不指定实例依赖 ORACLE_SID sqlplus / as sysdba -- 指定 pfile 启动绕过有问题的 spfile SQL startup pfile/u01/app/oracle/product/11.2.0/dbhome_1/admin/orcl/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 数据库装载完毕。 数据库已经打开。注意这里的Total System Global Area是 612368384 字节约 584M和出问题的那个 396M 不一样——这说明 pfile 里记录的是建库时的原始内存配置startup pfile确实绕开了被改坏的 spfile。这条命令的意义不在于「启动了」而在于它证明了一件事数据文件、控制文件、redo 全是好的坏的只有 spfile 一个文件。这个判断直接把排查范围从「整个数据库坏了」缩到「一个参数文件坏了」心态和方向都不一样。路径要用单引号包住且必须是绝对路径相对路径在sqlplus里不认当前目录会报 ORA-01078 或 LRM-00109。另外如果ORACLE_SID没设startup会提示无法找到实例这时候用startup pfile...仍然不行得先export ORACLE_SIDorcl。3.2 从 pfile 重建 spfile既然确认了 spfile 有问题最干净的处理方式是用 pfile 重新生成一份 spfile覆盖掉坏的。这里有个顺序问题必须先在 nomount 或已打开的实例上执行CREATE SPFILE再重启不能先关库。-- 实例已用 pfile 启动的情况下从 pfile 生成 spfile SQL create spfile from pfile/u01/app/oracle/product/11.2.0/dbhome_1/admin/orcl/pfile/init.ora.8282011115435; 文件已创建。CREATE SPFILE的默认输出路径就是$ORACLE_HOME/dbs/spfile$ORACLE_SID.ora同名文件会被直接覆盖。这个行为要心里有数一旦执行原来那个坏的 spfile 就没了所以第 4 章的备份不是可选项。如果想保留原文件做分析可以显式指定create spfile/tmp/spfile_new.ora from pfile...先生成到别的路径比对后再挪回去这一步在需要查「到底哪个参数写错了」时很有用。接下来正常关闭并重启验证 spfile 已经恢复SQL shutdown immediate; 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL startup mount; ORACLE 例程已经启动。 Total System Global Area 415236096 bytes ... 数据库装载完毕。startup mount只到 mount 阶段就够了参数文件是否可读、SGA 是否分配成功到这一步已经能看出来。确认没问题再alter database open打开。3.3 确认参数文件已经换回来重启后必须用两条命令做确认不能凭「起来了就算好了」SQL show parameter spfile; NAME TYPE VALUE --------- -------- ------------------------------------ spfile string /u01/app/oracle/product/11.2.0/dbhome_1/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 parameter spfile返回了路径说明实例确实从 spfile 启动重建成功了如果这一列是空的说明它还在用 pfile 启动后续所有ALTER SYSTEM SET ... SCOPESPFILE都不会落盘改了等于没改。show parameter sga则确认了当前生效的 SGA 大小是 396M也就是回到了建库时的水平。到这里应急处理结束库恢复了。但注意这是「恢复到出事之前」SGA 优化没做成下一章处理怎么在安全前提下改。4. 正确改 SGA先备份再动 spfile应急完事之后不能就这么算了原来的需求扩 SGA还挂着。这一章解决两件事改之前的备份做到什么程度算够以及参数到底怎么算才不会再把它改挂。4.1 备份 dbs 目录是唯一可靠的后悔药项目原文里的方法三说的就是这件事改参数前先把$ORACLE_HOME/dbs整个目录备份一份出问题时把spfileSID.ora拷回去就能启动。这条是三个方法里最该形成习惯的。# 备份整个 dbs 目录带日期后缀 cd $ORACLE_HOME cp -rp dbs dbs_bak_$(date %Y%m%d_%H%M) # 确认备份里包含 spfile 和密码文件 ls -l $ORACLE_HOME/dbs_bak_*/spfile${ORACLE_SID}.ora ls -l $ORACLE_HOME/dbs_bak_*/orapw${ORACLE_SID}dbs目录不只是放参数文件密码文件orapwSID、oratab之外的初始化脚本也在这里整目录拷贝比只拷spfileSID.ora更稳。-rp保留权限和属主这点很关键——拷回来的文件属主变成 root 或权限变成 644Oracle 会拒绝读取报 ORA-01078 或 ORA-27037等于白备份。另外强烈建议额外导出一份文本参数作为可读的「参数快照」-- 把当前 spfile 导成文本便于 diff 比对改了哪些参数 SQL create pfile/tmp/pfile_before_$(date).ora from spfile;有了这份文本改完再导一份diff一下就知道到底哪几个参数变了不用靠记忆。这种「改前导一份、改后导一份」的习惯在参数越调越乱的库上价值极高。4.2 SGA 参数怎么算才不改挂改挂的根因几乎都是取值超出物理内存或与其它参数冲突。几个硬约束要记牢参数含义约束sga_max_sizeSGA 可增长的上限不能超过物理内存减去 OS 占用且改它需重启sga_target自动管理的 SGA 目标值必须 ≤sga_max_size设 0 表示关闭 ASMMmemory_target自动内存管理总量与sga_target同设会冲突二选一pga_aggregate_targetPGA 总量与memory_target同设也会冲突以一台 8G 内存的测试机为例SGA 给到 2G~3G 是常见区间sga_max_size一定要留出 OS 和 PGA 的空间。改的时候分两步走先改可动态调整的sga_max_size单独留到重启窗口-- 第一步只改 spfile不立即生效避免当场把实例搞挂 SQL alter system set sga_target2500M scopespfile; SQL alter system set pga_aggregate_target800M scopespfile; -- sga_max_size 不能在运行中改同样写进 spfile下次重启生效 SQL alter system set sga_max_size3G scopespfile;scopespfile的意思是只写参数文件、不动当前实例这样即使参数算错了当前库还活着能在重启前用create pfile from spfile导出来检查一遍。反之scopeboth会立即尝试分配内存算错时当场报 ORA-00821SGA 目标大于最大值或直接让实例出问题在生产上非常危险。改完不要马上shutdown先做一次语法与取值检查-- 确认写入 spfile 的值符合预期且没有冲突参数 SQL show parameter sga; SQL show parameter memory_target; SQL create pfile/tmp/pfile_after.ora from spfile;然后diff /tmp/pfile_before.ora /tmp/pfile_after.ora确认只变了预期的那几行。这一步花不了一分钟但能避免下一次重启才发现参数写错。注意如果实例当前是memory_target自动内存管理模式直接把sga_target设上去会报 ORA-00838。正确做法是先把memory_target0重启再设sga_target分两次重启完成切换。5. 避坑与排查五条血泪经验下面这几条都是实际撞出来的按「现象 → 原因 → 解决」记碰到了可以直接对号。现象一startup pfile报 LRM-00109说找不到参数文件。原因基本是路径写错尤其是$ORACLE_HOME和实际安装路径不一致或者文件名那串时间戳抄漏了一位。解决先ls确认文件存在再复制路径别手敲也可以先cd到 pfile 目录用绝对路径拼。现象二重建 spfile 后重启show parameter spfile还是空的。原因是重建时把 spfile 生成到了别的路径比如显式指定了/tmp/spfile_new.ora或者ORACLE_SID在两次会话里不一致生成的文件名对不上。解决确认$ORACLE_HOME/dbs/spfile$ORACLE_SID.ora存在且ORACLE_SID和echo $ORACLE_SID的输出一致。现象三startup报 ORA-00821 或 ORA-00838 后实例直接退出。这是参数冲突或超限的典型报错。ORA-00821 是sga_target大于sga_max_sizeORA-00838 是memory_target和sga_target同时设置了非零值。解决用 pfile 启动create pfile from spfile导出文本用编辑器把冲突参数改成 0 或调到合规值再create spfile from pfile重建。这也是第 3 章那套流程能反复用的原因。现象四把备份的 spfile 拷回 dbs 目录仍然起不来报权限类错误。原因是cp时没带-p文件属主变成当前 shell 用户Oracle 后台进程读不了。解决chown oracle:oinstall spfileSID.ora chmod 640 spfileSID.ora或者干脆用cp -p从备份拷。这类问题最冤文件本身是好的栽在权限上。现象五改完 SGA 能启动但跑一段时间后被 OS 的 OOM killer 干掉。原因不是 Oracle 参数错是 SGA 加上 PGA 顶到了物理内存上限Linux 直接杀进程。解决free -g看实际可用内存SGA 加 PGA 留出至少 20% 给 OS 和文件缓存同时检查有没有hugepages没配导致页表开销过大。这个坑和参数文件无关但表现和「改 SGA 出事」一模一样容易误判。6. 装完怎么验证三条命令确认这次真的改对了恢复完成、参数也按计划改好了剩下最后一件事证明它稳。我的验证固定走三步缺一步都不算完。第一步确认参数文件链路正确SQL show parameter spfile; -- 必须返回具体路径空值说明还在用 pfile 启动改的参数没落盘 SQL select name, value, isspecified from v$spparameter where name in (sga_max_size,sga_target,pga_aggregate_target); -- isspecifiedTRUE 表示该参数在 spfile 中显式设置过v$spparameter这个视图比show parameter更可靠它读的是 spfile 里真实存了什么而不是实例内存里的当前值。isspecified为 TRUE 才是真的写进去了如果某一行是 FALSE说明 spfile 里没这个参数实例用的是默认值下次重启可能又变回去。第二步做一次完整的正常重启而不是只看当前状态SQL shutdown immediate; SQL startup; SQL show parameter sga;当前实例开着不代表重启能起来参数文件的问题只有重启才暴露。这一步是唯一能证明「下次真出问题重启时不会挂」的手段。我会在重启后顺手看一眼告警日志尾部确认没有 ORA- 报错和 SGA 相关的警告tail -50 $ORACLE_BASE/diag/rdbms/${ORACLE_SID}/${ORACLE_SID}/trace/alert_${ORACLE_SID}.log第三步压一下内存看是否有隐患。用sysbench或简单的并发查询把 SGA 用起来同时开另一个窗口free -m盯剩余内存确认没有往 swap 里猛灌。如果 swap 使用量持续上涨说明 SGA 加 PGA 的总量还是给多了趁业务低峰再往下调别等 OOM killer 来提醒。验证通过后把那两份 pfile 快照和 dbs 目录的备份归档到固定位置命名带上日期和变更说明。这套东西平时看着占地方真出事的时候就是能省下半小时排查的后悔药。从那以后我每次动 SGA 参数不管多小的库都强制走一遍「备份 dbs → 导 pfile 快照 →scopespfile改 → 重启验证 → 看告警日志」这条链一次没落过。吃过一次改完参数库起不来的亏就知道那几分钟的准备时间有多便宜。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →