简介围绕 Oracle SGA 参数调整引发数据库启动异常这一常见故障这份文档面向数据库运维人员与 Oracle 初学者梳理从应急启动到恢复实例的处理思路。内容以实际命令与参数输出为依据涵盖用 PFILE 临时启动、由 PFILE 重建 SPFILE、直接修正 PFILE 中的 SGA 错误参数以及调整前备份 SPFILE 等做法并提示内存分配、启动验证与性能测试等注意点。压缩包仅含 1 个 docx 文件大小约 14KB篇幅精简适合作为排障时的速查笔记或操作参照。该资源已有 328 人学习说明其对日常运维场景具有一定参考价值。读者可从中获得一套可对照执行的恢复路径理解 SPFILE 异常时的判断依据并借助命令回显核对 SGA 与实例启动状态减少因参数改错导致停机的风险。1. 改完 SGA 重启失败先别急着重装库半夜改完sga_targetshutdown immediate一切正常startup却直接卡在 nomount屏幕上跳出 ORA-00838、ORA-27102 或者干脆一句“例程已经启动但数据库装载失败”——这种场面我遇到过不止一次。改 SGA 引发的启动异常是 Oracle 运维里最典型的“一行参数换一夜排查”尤其在没有备份 spfile 的时候不少人的第一反应是重装数据库其实绝大多数情况下实例本身没有损坏出问题的是那份被写进 spfile 的 SGA 参数。这篇笔记面向的读者很明确手上有 Linux 上的 Oracle 单实例刚调整过sga_max_size、sga_target或memory_target现在数据库起不来。下面按“先找参数文件、再走三条恢复路径、最后冷启动验证”的顺序说透。2. 恢复前的环境盘点先把 pfile、spfile 和内存上限找准SGA 改错之后最怕的不是报错是瞎试。很多人第一反应是反复startup、反复改参数结果把原本还能救的 spfile 改得面目全非。我一般会在动手之前先花三五分钟确认三件事当前实例到底在读哪个参数文件、$ORACLE_HOME/dbs目录下有什么、操作系统层面允许多大的共享内存。这三件事不清楚后面三条恢复路径都是碰运气。2.1 pfile 与 spfile 的区别以及启动时到底读谁Oracle 实例启动分三步nomount、mount、open。nomount 这一步不读控制文件只读参数文件而参数文件决定了 SGA 分配多大、后台进程起几个、控制文件在哪儿。参数文件有两种形态pfile 是纯文本默认名initSID.oraspfile 是二进制默认名spfileSID.ora两者默认都放在$ORACLE_HOME/dbs下。文本的能直接用 vi 改二进制的只能用create spfile或alter system set ... scopespfile来改这就是改 SGA 出事之后 pfile 反而成了救命稻草的原因。启动写法读取的文件典型用途startup优先spfileSID.ora没有才退回initSID.ora日常启动startup pfile/绝对路径/init.ora.xxx指定文本文件应急启动、参数回滚startup nomount同上停在 nomount重建 spfile、重建控制文件create spfile from pfile...读 pfile 写 spfile把正确的文本参数固化先把目录翻开看一眼别凭记忆# 切到 oracle 用户避免权限导致的假报错 su - oracle # 列出参数文件目录重点看 spfileSID.ora 和 initSID.ora 的时间戳 ls -l $ORACLE_HOME/dbs # 应急 pfile 一般不在 dbs 下而在 admin 目录里按时间排序找最新的 ls -lt $ORACLE_BASE/admin/$ORACLE_SID/pfile/ | head这里要说明两点$ORACLE_HOME/dbs里的spfileSID.ora是二进制文件用cat看会是一堆乱码别以为文件坏了$ORACLE_BASE/admin/SID/pfile/下的init.ora.8282011115435这类文件是每次用create pfile或者安装时生成的文本快照文件名后半段通常是时间戳按修改时间倒序排一下就能找到最近一份可用参数。2.2 用一条 show parameter 判断实例在用哪个文件实例起不来不等于连不上。只要 Oracle 的后台进程还在sqlplus / as sysdba依然能连进去哪怕连的是一个空闲实例也能执行startup。这是很多人不知道的一点以为库打不开就没法操作了实际上 nomount 状态下照样能建 spfile、能改参数。-- 以 sysdba 身份本地登录不经过监听密码文件有问题也能进 sqlplus / as sysdba -- 查当前实例使用的 spfile 路径 -- 返回非空实例由 spfile 启动返回空实例由 pfile 启动 show parameter spfile; -- 顺便看一眼 SGA 相关几个值方便和后面重建后的值做对比 show parameter sga;show parameter spfile的输出很关键。如果 VALUE 一列显示的是一个具体路径说明当前实例是拿 spfile 起的那么“改 SGA 改出问题”基本可以锁定为 spfile 里的参数写错了如果 VALUE 是空的说明用的是 pfile那就直接去改文本文件。另外show parameter sga会列出sga_max_size、sga_target、lock_sga、pre_page_sga四个值记下当前数值等会儿重建完 spfile 要拿它做对照。如果实例连 nomount 都进不去sqlplus会提示连接到空闲实例这时候去看告警日志路径按版本不同分两种常见做法是两个都试一下# 11g 及以后diag 目录下的 alert 日志 tail -100 $ORACLE_BASE/diag/rdbms/$ORACLE_SID/$ORACLE_SID/trace/alert_$ORACLE_SID.log # 10g 时代的老路径升级过的库可能还留着 tail -100 $ORACLE_BASE/admin/$ORACLE_SID/bdump/alert_$ORACLE_SID.log # 只抓报错行日志几百兆的时候别整篇翻 grep -nE ORA-|Error $ORACLE_BASE/diag/rdbms/$ORACLE_SID/$ORACLE_SID/trace/alert_$ORACLE_SID.log | tail -30日志里最先出现的那条 ORA 才是根因后面一串往往是连锁反应。比如先报 ORA-27102out of memory接着才报 ORA-00821specified value of sga_target is too small你要解决的是前者不是后者。2.3 改 SGA 之前先看物理内存和内核共享内存上限SGA 本质是一块共享内存段Oracle 向操作系统申请操作系统给不给是另一回事。sga_max_size设成 32G机器只有 16G 物理内存startup一定失败而且报错信息往往并不直白。所以恢复之前先确认系统侧的三组数# 物理内存和 swap确认 SGA 总量别超过 MemTotal 的合理比例 free -m # 内核共享内存参数shmmax 是老版本单段共享内存的上限 sysctl kernel.shmmax kernel.shmall kernel.shmmni # 当前系统里已经存在的共享内存段单位是字节 ipcs -lm # 如果开了大页确认大页数量和页大小 grep -i huge /proc/meminfo参数含义用一句话说清kernel.shmmax是单个共享内存段的最大字节数SGA 在老版本里必须装进一段所以它必须大于sga_max_sizekernel.shmall是所有共享内存页的总量页大小通常是 4096 字节所以shmall至少得等于shmmax / 4096kernel.shmmni是共享内存段个数上限一般不用动。我把这三个值和 SGA 的对应关系整理成一张表改参数前扫一眼就能判断会不会翻车系统项查看命令与 SGA 的关系物理内存free -mSGA PGA 建议不超过物理内存的 70%80%kernel.shmmaxsysctl kernel.shmmax需大于等于sga_max_size字节kernel.shmallsysctl kernel.shmall需大于等于shmmax / 4096/dev/shm大小df -h /dev/shm使用 AMMmemory_target时需大于memory_target这里有个血泪经验如果实例用的是memory_target自动内存管理Oracle 会去挂/dev/shm很多云主机默认/dev/shm只有物理内存的一半memory_target一调大就报 ORA-00845。这不是 SGA 参数写错了是文件系统太小mount -o remount,size8G /dev/shm之后就好了。搞清楚这层关系再往下走恢复步骤才不至于把方向搞反。3. 方法一实战用 pfile 应急启动并重建 spfile三条恢复路径里这一条最稳妥也最像“外科手术”先用一份文本参数把实例拉起来再从这份文本反向生成一个干净的 spfile把坏掉的二进制文件替换掉。原文给的就是这个思路我把中间的判断点和容易漏的收尾动作补全。3.1 用 init.ora 文件把实例拉起来假设已经在$ORACLE_BASE/admin/SID/pfile/下找到了最近那份init.ora.8282011115435接下来的动作是带pfile参数启动。注意路径必须写绝对路径而且必须对 oracle 用户可读。-- 本地以 sysdba 登录不依赖监听 sqlplus / as sysdba -- 用指定的文本参数文件启动实例 -- 路径按自己环境替换别照抄 SID startup pfile/oracle_install/admin/SID/pfile/init.ora.8282011115435;如果这条命令能走到“数据库已经打开”事情就简单了一半。启动输出里的Total System Global Area是这一时刻实际分配的共享内存总量原文那次是 612368384 字节换算一下 612368384 / 1024 / 1024 ≈ 584M说明这份 pfile 里的 SGA 参数是 584M 左右和后来重建 spfile 之后的 396M 不是一套值——这一点很重要它说明 pfile 和 spfile 里的参数本来就不一致谁对谁错要以业务实际需要为准不能盲目相信任何一份。这里有几个高频卡点报 ORA-01078 加 LRM-00109基本是路径写错或者文件名打错报 ORA-27037 加 Linux-x86_64 Error: 13是权限问题pfile 属主不是 oracle 或者没有读权限报 ORA-27102 则是内存真的要不到回到 2.3 节核对shmmax和物理内存。3.2 从 pfile 生成 spfile绕过 ORA-32002实例用 pfile 起来之后第一件事不是急着改业务而是把这份可用的文本参数固化成一个新的 spfile。这一步的顺序有讲究很多人在这里踩坑-- 用当前可用的 pfile 生成默认位置的 spfile -- 不带路径时写到 $ORACLE_HOME/dbs/spfileSID.ora create spfile from pfile/oracle_install/admin/SID/pfile/init.ora.8282011115435; -- 也可以显式指定输出路径方便先做对比再替换 -- create spfile/tmp/spfileSID.ora.new from pfile/oracle_install/admin/SID/pfile/init.ora.8282011115435;命令返回“文件已创建”说明二进制参数文件已经生成。这里有一个必须说清的限制create spfile from pfile在实例已经由 spfile 启动的情况下会直接报 ORA-32002cannot create SPFILE already being used by the instance。换句话说这条命令之所以能执行成功前提正是当前实例是用 pfile 起的。这也是方法一必须先startup pfile再create spfile的原因顺序颠倒就白忙一场。生成完别急着shutdown先确认一下文件确实落到了默认位置、属主是 oracle# 看新生成的 spfile时间戳应该是刚刚 ls -l $ORACLE_HOME/dbs/spfile* # 属主不对就改回来否则下次启动会报权限错误 chown oracle:oinstall $ORACLE_HOME/dbs/spfile$ORACLE_SID.ora chmod 640 $ORACLE_HOME/dbs/spfile$ORACLE_SID.ora3.3 shutdown 之后用 spfile 重启核对参数是否回正新 spfile 就位接下来做一次完整的关闭—启动循环让实例真正从 spfile 读参数。原文走的是shutdown immediate再startup mount我一般会补上alter database open因为 mount 状态只能证明参数文件读对了、控制文件找到了不能证明数据文件全都正常。-- 正常关闭此时实例跑在 pfile 上关闭不会有问题 shutdown immediate; -- 不带参数启动默认读 $ORACLE_HOME/dbs/spfileSID.ora startup mount; -- 确认当前用的确实是 spfile而不是又退回了 pfile show parameters spfile; -- 核对 SGA 两个核心参数是否回正 show parameter sga; -- mount 通过后打开数据库这一步才真正验证数据文件可用 alter database open;show parameters spfile返回一个非空路径说明 spfile 已经生效show parameter sga里sga_max_size和sga_target如果都是 396M对应 415236096 字节说明参数已经回正到目标值。这里要提醒一点sga_target不能大于sga_max_size如果 pfile 里两个值写反了启动时照样会报 ORA-00823重建 spfile 也救不了必须回到第 4 章去改文本文件。最后把这次可用的 pfile 和 spfile 各留一份副本放到一个带日期的目录里。这份副本就是下次改参数出问题时的后悔药比什么文档都管用。4. 方法二实战直接改 pfile 里的 SGA 参数方法一是“用好的文本覆盖坏的二进制”方法二则是“把文本本身改对”。两条路经常配合使用先用方法一把库拉起来再回头用方法二把 pfile 里的参数修到业务需要的大小。这一步的关键不在命令而在于搞清楚那几个 SGA 参数之间谁管谁。4.1 先读懂 pfile 里跟 SGA 相关的几行打开init.ora.8282011115435用 grep 过滤出内存相关参数别一行行翻# 只抓内存相关参数注释行也带上方便看原始说明 grep -nE sga_|memory_|db_cache|shared_pool|large_pool|java_pool|pga_aggregate \ /oracle_install/admin/SID/pfile/init.ora.8282011115435输出的每一行都是参数名值的格式值可以带单位后缀 K、M、G不带单位默认是字节。下面这张表是我按实际使用频率整理的改之前对着看一遍基本不会改错参数含义与其他参数的关系sga_max_sizeSGA 能达到的上限运行时可增不可超必须大于等于sga_targetsga_target自动共享内存管理的目标值与memory_target互斥二者只能留一个memory_targetSGA PGA 的总目标走 AMM与sga_target、pga_aggregate_target互斥db_cache_size数据缓冲区手工管理时用开了sga_target后一般留 0 或不写shared_pool_size共享池手工管理时用同上pga_aggregate_targetPGA 总量走 ASMM 时用与memory_target互斥最容易出事的是memory_target和sga_target同时存在。这两个参数一旦并存实例启动时会报 ORA-00838 或 ORA-01078 一类的错误因为 Oracle 不知道该听谁的。改之前先确认只保留一套要么全用memory_targetAMM要么用sga_max_size加sga_target加pga_aggregate_targetASMM。这是改 SGA 异常里占比很高的一类很多“改完起不来”根本不是值设大了是两套参数打架。4.2 用 vi 改文件同时保住属主和权限改文件之前先备份这一步别省。文本文件改坏了还能回滚不备份就只能靠记忆重写。# 先备份文件名带日期出问题一条 cp 就回去 cp /oracle_install/admin/SID/pfile/init.ora.8282011115435 \ /oracle_install/admin/SID/pfile/init.ora.8282011115435.bak # 编辑只改 SGA 相关那几行别动其他 vi /oracle_install/admin/SID/pfile/init.ora.8282011115435 # 改完确认属主和权限必须是 oracle 可读 ls -l /oracle_install/admin/SID/pfile/init.ora.8282011115435改的时候记住三条规则单位写清楚4G比4294967296好读也好核对sga_target不要超过sga_max_sizesga_max_size不要超过物理内存的 70% 左右留出 PGA 和操作系统本身的开销。如果机器上还跑了别的实例把各个实例的 SGA 加起来一起算别单看一个。权限这块补充一句pfile 属主错成 rootstartup pfile会报 ORA-27037 加 Error: 13报错信息里不会直接说“权限不对”新手很容易在这里绕圈。常见做法是改完统一执行一次chown oracle:oinstall加chmod 640养成习惯之后就不会再被这个坑绊住。4.3 用改好的 pfile 启动再把参数固化进 spfile改完文本先验证再固化顺序不能反-- 用改过的 pfile 启动能起到 open 才算改对了 startup pfile/oracle_install/admin/SID/pfile/init.ora.8282011115435; -- 确认 SGA 实际分配值和预期一致 show parameter sga; -- 确认没有 memory_target 和 sga_target 并存的冲突 show parameter memory_target;如果启动成功且show parameter sga的值符合预期再执行一次create spfile from pfile...把这份正确的文本固化成二进制参数文件然后shutdown immediate加不带参数的startup让实例回到默认读 spfile 的常规状态。反过来如果改完 pfile 还是起不来别继续在 pfile 上反复试把备份的.bak拷回去用方法一把实例先拉起来再慢慢调整——库里还有业务数据的时候能先开起来比参数调得漂亮重要得多。5. 避坑与排查改 SGA 前后最容易翻车的五个点这一节单独拎出来是因为下面五条几乎每一条我都在现场见过。按“现象 → 原因 → 解决”的顺序写遇到对应症状直接对号入座。第一条create spfile from pfile 报 ORA-32002现象是执行create spfile from pfile...时提示 cannot create SPFILE already being used by the instance。原因很直接当前实例是由 spfile 启动的Oracle 不允许覆盖正在使用的二进制参数文件。解决办法是先startup pfile...用文本参数把实例拉起来再执行一次create spfile from pfile或者用create spfile/tmp/spfileSID.ora.new from pfile...先输出到临时路径关闭实例后手工替换。第二条改了 pfilestartup 之后参数却没变现象是明明 vi 改过文本文件重启后show parameter sga还是老值。原因是startup默认优先读$ORACLE_HOME/dbs/spfileSID.ora根本没碰你改的那份 pfile。解决办法是启动时显式加pfile参数改完之后一定要走“create spfile from pfile → shutdown → startup”这一整套只改文本不固化等于没改。第三条改大 SGA 后报 ORA-27102 或 Linux-x86_64 Error: 28现象是startup直接停在 nomount告警日志里先是 ORA-27102: out of memory后面跟着一串 ORA-00821。原因是物理内存不够或者kernel.shmmax小于sga_max_size内核不让分配这么大的共享内存段。解决办法是把sga_max_size降回物理内存的合理比例或者用 root 调整kernel.shmmax、kernel.shmall后sysctl -p生效再重启实例。调内核参数属于系统级操作改之前记下原值。第四条开了 memory_target 之后报 ORA-00845现象是startup报 ORA-00845: MEMORY_TARGET not supported on this system。原因不是内存不够是/dev/shm太小AMM 依赖这个挂载点。解决办法是用df -h /dev/shm确认大小再用 root 执行mount -o remount,size8G /dev/shm临时放大要永久生效就写进/etc/fstab。这条坑的迷惑性在于报错文字说的是“不支持”实际只是空间不足。第五条spfile 被覆盖之后没有退路现象是新 spfile 生成完、实例重启失败想回退却发现原来的spfileSID.ora已经被覆盖$ORACLE_HOME/dbs下只剩一个坏文件。原因是执行create spfile from pfile时没先备份默认位置的老文件。解决办法只能是回到上一份可用的 pfile 重新生成如果 pfile 也没留就只能从备份集或者备库上想办法了。所以我现在改任何 SGA 参数之前都会先把整个$ORACLE_HOME/dbs目录打包一份这个动作花不了十秒但它是唯一能在关键时刻兜底的黑匣子。6. 把备份做在改参数之前一次冷启动验证整条恢复链路方法三听起来最不起眼却是唯一能让你在出事之后不慌的一条改参数之前先把$ORACLE_HOME/dbs整个目录备份出来出问题直接拷回去。# 改 SGA 之前执行目录整体打包带日期戳 tar -czf /backup/dbs_$(date %Y%m%d_%H%M).tar.gz -C $ORACLE_HOME dbs # 出问题之后回滚先把当前目录挪走而不是直接删 mv $ORACLE_HOME/dbs $ORACLE_HOME/dbs.broken tar -xzf /backup/dbs_20240101_2300.tar.gz -C $ORACLE_HOME # 恢复后确认属主再启动 chown -R oracle:oinstall $ORACLE_HOME/dbs回滚之后别急着收工走一遍完整的冷启动验证确认恢复出来的不只是“能起来”而是“能正常用”验证项命令通过标准参数文件类型show parameter spfile返回 spfile 路径非空SGA 实际值show parameter sgasga_max_size≥sga_target且不超过物理内存实例状态select status from v$instance;返回 OPEN内存段select * from v$sgainfo;各池大小与实际分配一致日志干净度grep ORA- alert_$ORACLE_SID.log最近一次启动无新 ORA 报错最后一步我会跑一条真实业务查询哪怕只是select count(*) from dba_users;也要让 SQL 真正解析执行一遍。因为实例 open 只代表数据文件和控制文件对得上buffer cache 和 shared pool 能不能正常工作得有一条 SQL 走完全程才算数。从那以后我每次动 SGA 参数都强制自己先打包$ORACLE_HOME/dbs、再留一份create pfile的文本快照然后才允许自己敲alter system set。参数可以慢慢调回滚的路必须先铺好。希望帮到你。本文还有配套的精品资源点击获取