2026/10/17 21:48:38

Oracle调整SGA后启动失败?三步用pfile应急恢复实例

Oracle调整SGA后启动失败?三步用pfile应急恢复实例 简介Oracle数据库运维中因调整SGA参数导致实例无法启动是常见故障之一这类问题通常源于spfile中SGA_MAX_SIZE、SGA_TARGET等内存值设置错误或超出物理内存限制。这份资源面向DBA、运维工程师及Oracle初学者以Linux环境下一个完整的应急启动过程为案例先解释了SGASystem Global Area、spfile与pfile三者之间的关系与调用顺序再按优先级给出三种可落地的处理办法一是利用pfile应急启动数据库并用create spfile from pfile重建spfile二是直接修改pfile中SGA_MAX_SIZE等错误参数后重新启动三是在调整SGA前备份spfileSID.ora以便故障时快速回滚。文档中附有具体SQL命令、启动日志、参数校验输出以及根因分析思路能帮助读者在遇到类似内存配置问题时快速定位并恢复数据库。资源共1个docx文件压缩包仅14KB内容精炼、重点突出便于本地查阅和应急参考目前已有326人学习适合需要维护Oracle内存参数或处理启动故障的运维人员借鉴。1. 改成 SGA 参数后数据库再也起不来DBA 最不想碰到的启动故障之一改动 SGA 参数之后数据库再也起不来这句话在 Oracle 运维里几乎每周都会出现一次。你只是按网上教程把sga_max_size、sga_target调大shutdown immediate再startup结果实例要么刚启动就报ORA-27102、ORA-00824要么数据库打开到一半直接回滚。麻烦的是错误日志看起来很玄学参数值没超过物理内存操作系统负载也正常但库就是起不来反复重启只会浪费时间。更气人的是这类故障往往不是数据文件损坏也不是权限问题纯粹是参数文件里一组自相矛盾的内存配置在作怪。下面就把这条血泪经验拆开讲为什么改 SGA 会触发启动失败、怎么用一份旧 pfile 把库应急拉起来、以及以后再调内存参数时怎么避免翻车。适合正在被一个起不来的库卡住的开发者或 DBA——按文中步骤操作大概率能在十几分钟内让数据库恢复可用。2. 为什么改个 SGA 就能把库改到起不来内存参数背后的启动链路2.1 实例启动的第一步就是拿参数去分配 SGAOracle 实例的启动分为 NOMOUNT、MOUNT、OPEN 三个阶段。第一阶段 NOMOUNT 只做一件事读取参数文件里与内存相关的配置为实例分配 SGASystem Global Area并启动后台进程。SGA 里最重要的几块是 Database Buffers数据缓冲区、Shared Pool共享池、Redo Buffers重做日志缓冲区它们的大小由sga_max_size、sga_target、db_cache_size、shared_pool_size、log_buffer这些参数共同决定。也就是说SGA 的分配发生在整条启动链路的最前面。只要参数文件里的内存值有问题数据库连 NOMOUNT 都过不去后面的 MOUNT、OPEN 根本没机会执行。这就是为什么改 SGA 导致启动异常的报错几乎都集中在startup命令发出的前几秒——实例连自己都还没建立起来更谈不上打开数据库。如果看到的现象是执行startup后立刻弹ORA-27102、ORA-00824、ORA-00845这类错误或者在告警日志里发现shmget/shmctl/mmap失败之类的记录那基本可以断定问题出在参数文件而不是数据文件或控制文件。这是后续所有处理方法的共同前提先判断故障域再去动参数别一上来就怀疑数据文件损坏那会把人带进死胡同。2.2 SPFILE 像个黑匣子改错的参数也会被原样写进去从 9i 开始Oracle 默认使用 SPFILE服务器参数文件位于$ORACLE_HOME/dbs/spfileSID.ora。SPFILE 的特点是参数以二进制保存、带生命周期SCOPESPFILE/MEMORY/BOTH、由实例统一管理。但这也意味着它是个黑匣子你用ALTER SYSTEM SET sga_target2G SCOPESPFILE写进去一条错误配置时Oracle 不会因为这个值明显不合理就拒绝不少内存参数的校验要等下一次实例启动、真正尝试分配内存时才会暴露。更隐蔽的是SPFILE 里往往残留着大量历史参数。很多人调 SGA 只盯着sga_target和sga_max_size却没注意db_cache_size、shared_pool_size、log_buffer这些组件参数是不是也留在文件里。当 SGA 各部分的取值互相矛盾——比如各组件之和超过sga_max_size或者sga_target超过了sga_max_size——实例在启动时找不到一个自洽的内存布局会直接失败。时报什么错取决于具体冲突类型常见的有四类ORA-00824SGA_TARGET 指定值超过 sga_max_size目标值越过了硬上限。ORA-00838MEMORY_TARGET 指定值过小装不下 SGA 各组件的总和。ORA-27102共享内存分配失败通常是超过了 Linux 内核参数 shmmax 的限制。ORA-00845MEMORY_TARGET 无法分配/dev/shm 空间不足。注意自洽这个问题在 pfile 时代反而不容易出现——文本文件里每个参数写得清清楚楚DBA 一眼能看出矛盾。SPFILE 把参数藏起来了也就把错误藏起来了。所以许多有经验的 DBA 在调 SGA 前都会先执行create pfile from spfile留一份可读的文本配置目的就是给黑匣子留一扇窗。2.3 启动失败先要分清是参数组合错还是操作系统限额改 SGA 导致启动失败的根因其实分成两大类排查方向完全不同。第一类是 Oracle 自身参数组合错误。比如sga_target大于sga_max_size或者非自动管理模式下各组件参数之和超出sga_max_size。这类错误的特点是报错信息是ORA-00824、ORA-00838这类带参数名的错误把参数改回合理值后实例立刻能起。第二类是操作系统层面给的内存限额不够。Linux 下最常见的场景是把sga_max_size调得比/proc/sys/kernel/shmmax还大Oracle 用共享内存段shmget创建 SGA 时失败报ORA-27102: out of memory或者用了 11g 起的自动内存管理memory_target但/dev/shm这个 tmpfs 分区比memory_target还小报ORA-00845。这类错误的特点是无论怎么改 pfile只要目标内存值超过系统限额就起不来必须先调内核参数或换内存管理方式。区分这两类有一个很实用的办法用一份已知能起来的 pfile 应急启动。如果小配置能起来、大配置起不来就是操作系统限额如果一份自洽的旧配置能起来而当前 spfile 起不来就是参数组合问题。下面方法一用的正是这个思路先把库拉起来、再判断到底是哪一类。报错代码故障域原因方向对策方向ORA-00824 / ORA-00838Oracle 参数sga_target 超 sga_max_size或组件之和越界用 pfile 起库校正参数后重建 spfileORA-27102操作系统shmmax / 大页不足调内核参数或用大页再起库ORA-00845操作系统/dev/shm 小于 memory_target扩容 /dev/shm或改用 ASMM2.4 带时间戳的 init.ora 文件就是救命的后悔药在 Linux 上遇到这种故障先去两个地方翻文件$ORACLE_BASE/admin/SID/pfile/目录下的init.ora.时间戳文件以及$ORACLE_HOME/dbs/下的initSID.ora。init.ora.8282011115435这种带时间戳的命名就是之前某次操作留下的 pfile 快照要么是调参前手动create pfile from spfile做的备份要么是创建实例时留下的初始模板。文件名的数字段就是快照时间——这里对应 8 月 28 日 11 点 54 分 35 秒。这份文件价值在于它记录的是上一次还能正常启动时的内存参数。只要不是把内核限额也一起改小了用这份 pfile 启动几乎必然能绕过 spfile 里写坏的那组参数。所以看到数据库启动异常的报错第一反应不应该是去改一堆参数碰运气而是先去 pfile 目录里找这份自洽配置。找不到再考虑重建找到了就等于拿到了后悔药。3. 方法一用旧 PFILE 应急启动并重建 SPFILE首选方案3.1 先在 Linux 上定位 pfile 文件的真实位置方法一的核心就一句话绕过写坏的 spfile用一份自洽的 pfile 把实例拉起来再用这份 pfile 重新生成 spfile。第一步是找到这份 pfile。在 Linux 环境下Oracle 的 pfile 一般存放在$ORACLE_BASE/admin/$ORACLE_SID/pfile/目录其中$ORACLE_BASE是安装软件的根目录对应资料里写的oracle_install$ORACLE_SID是实例名比如 orcl。用以下命令确认文件位置和内容# 确认当前环境变量SID 必须和出问题的实例一致 echo $ORACLE_SID $ORACLE_HOME $ORACLE_BASE # 列出 pfile 目录下的文件按时间倒序最新的一般最接近可用状态 ls -lt $ORACLE_BASE/admin/$ORACLE_SID/pfile/ # 检查 pfile 里的内存参数是否自洽只看关键行 grep -E sga_max_size|sga_target|memory_target|db_cache_size|shared_pool_size|log_buffer \ $ORACLE_BASE/admin/$ORACLE_SID/pfile/init.ora.8282011115435这段命令里ls -lt按修改时间倒序列出 pfile 备份时间戳越新的init.ora.xxx越可能是改坏之前的最近一份配置grep的作用是验证这份 pfile 里写的sga_max_size、sga_target是否满足target 不大于 max_size这个基本约束。实际操作时别跳过 grep——如果 grep 出来的值本身就矛盾比如sga_target2G而sga_max_size1G这份 pfile 也不能直接用于启动得先跳到方法二把值改对。提示$ORACLE_BASE 与 $ORACLE_HOME 是两个不同路径pfile 备份通常在 $ORACLE_BASE/admin/ /pfile而 spfile 在 $ORACLE_HOME/dbs 下。找错目录是新手最常踩的坑。3.2 执行 startup pfile让实例绕过 SPFILE确认 pfile 内容没问题后用 SQL*Plus 以 sysdba 身份连接执行应急启动命令-- 以 sysdba 登录本地操作系统认证或密码认证均可 sqlplus / as sysdba -- 用指定的 pfile 启动实例绕过默认的 spfile startup pfile/u01/app/oracle/admin/orcl/pfile/init.ora.8282011115435;startup pfile后面必须跟绝对路径路径里的admin/orcl要替换成实际目录。这条命令的作用是告诉实例不要去找spfile$SID.ora直接用这份文本参数文件初始化 SGA。如果一切正常你会看到与资料里一致的输出先是ORACLE 例程已经启动然后打印Total System Global Area的大小并依次列出 Fixed Size、Variable Size、Database Buffers、Redo Buffers 四个部分——它们的总和就是 SGA。看到数据库已经打开说明实例已经从故障中恢复可以对外服务了。如果这一步也起不来大概率不是 spfile 的问题而是选定的 pfile 本身就超出操作系统限额ORA-27102或者/dev/shm不够ORA-00845。这时先别急着换 pfile按后面 5.2 和 5.3 的排查把系统限额确认了再说否则换几份 pfile 结果都一样。3.3 create spfile from pfile把修复结果固化下来pfile 启动成功只是应急如果实例下次还是去读写坏的 spfile故障必然复现。接下来的关键一步是用当前这份证明有效的 pfile 重新生成 spfile-- 用刚才成功启动的 pfile 重建 spfile create spfile from pfile/u01/app/oracle/admin/orcl/pfile/init.ora.8282011115435; -- 重建后先关闭实例让后续启动从新 spfile 走完整链路 shutdown immediate;create spfile from pfile是 Oracle 提供的参数文件互转命令默认会在$ORACLE_HOME/dbs/下生成spfile$ORACLE_SID.ora。它的意义在于spfile 里的每一项参数都来自刚才这份能启动的 pfile从源头上去掉了之前写坏的那组值。执行后屏幕会提示文件已创建此时旧 spfile 已被覆盖——如果你还想留后悔药创建前可以先把旧spfile$ORACLE_SID.ora复制一份到别的目录这就是方法三干的事。shutdown immediate用于把实例干净地停下来让后续startup从新生成的 spfile 重新走启动链路。注意shutdown immediate会回滚未提交事务并断开会话生产库操作前最好先确认没有重要的长事务在跑必要时先和业务方打个招呼。3.4 用 show parameter 验证实例确实吃的是 SPFILE重建 spfile 后再次启动并验证这一步不能省。很多人重建完直接startup没确认实例到底读的是 pfile 还是 spfile结果调了几个小时参数重启一次又打回原形-- 正常启动不指定 pfileOracle 会优先找 spfile$SID.ora startup mount; -- 确认当前实例使用的参数文件类型 show parameters spfile; -- 确认 SGA 相关参数的实际生效值 show parameter sga;startup mount会触发两次内存相关校验一次是 NOMOUNT 阶段分配 SGA一次是读取控制文件装载数据库输出里同样会打印Total System Global Area。如果实例真的在用 spfileshow parameters spfile的结果里 spfile 这一行会有值——资料里显示的是**DATABASE\SPFILEORCL.ORA这种平台相关写法Windows 上带注册表路径Linux 上通常是文件路径重点看值里包含 SPFILE 字样如果这一行是空值说明实例还在读 pfile需要检查 dbs 目录下 spfile 文件是否真的生成了。show parameter sga能看到两组关键参数sga_max_size和sga_target。资料里的输出显示这两个值都是 396M说明 ASMM 自动共享内存管理处于正常状态——sga_target有值且不超过sga_max_size后续你再调sga_target都不需要重启。验证通过后数据库已经回到用 spfile 正常管理的状态方法一就完成了。4. 方法二和方法三改配置文件与备份恢复两条退路4.1 方法二直接编辑 pfile把错误的 SGA 参数改回来方法二适合你已经明确知道是哪几个参数写错的情况。思路是先把 pfile 里的错误内存参数改成正确值再用这份修正版 pfile启动并重建 spfile。操作分三步。第一步复制一份 pfile 再改不要把原文件直接改坏。第二步用 vi 或 sed 修改关键参数sga_max_size、sga_target、db_cache_size、shared_pool_size、log_buffer等改动的原则是sga_target必须小于等于sga_max_size如果sga_target没配值为 0 或注释掉那db_cache_size、shared_pool_size、log_buffer等组件值之和不能超过sga_max_size。第三步用修正后的 pfile 启动验证后重建 spfile。# 1. 先备份原 pfile再复制一份用于修改 cp $ORACLE_BASE/admin/$ORACLE_SID/pfile/init.ora.8282011115435 \ $ORACLE_BASE/admin/$ORACLE_SID/pfile/init.ora.8282011115435.bak # 2. 用 vi 打开副本把 sga_target 调整到不超过 sga_max_size 的值 vi $ORACLE_BASE/admin/$ORACLE_SID/pfile/init.ora.8282011115435.bak-- 3. 用修正版 pfile 启动并重建 spfile startup pfile/u01/app/oracle/admin/orcl/pfile/init.ora.8282011115435.bak; create spfile from pfile/u01/app/oracle/admin/orcl/pfile/init.ora.8282011115435.bak; shutdown immediate; startup;这里有个细节值得说明create spfile from pfile生成的是当前这份 pfile 的完整快照。如果你只改了sga_target忘了同步sga_max_size生成出来的 spfile 依然带着错误组合下次启动还是会失败。所以方法二的关键不是会改参数而是改完要自查参数自洽——我一般会在改完后把文件里所有sga、memory开头的行逐行 grep 出来在心里过一遍大小关系再执行启动。多花这一分钟能省下一次重启验证的时间。4.2 方法三调参之前备份 spfile出问题一把还原方法三是治理层面最值得养成的习惯动手之前先把 spfile 备份好出了任何问题都能回滚。资料里特别强调做修改前先将oracle_install/product/dbs目录下的所有文件备份这里的product/dbs就是$ORACLE_HOME/dbs。这个目录里躺着spfile$ORACLE_SID.ora、init$ORACLE_SID.ora、orapw$ORACLE_SID口令文件、lk$ORACLE_SID锁文件等对启动至关重要的文件其中起决定作用的就是spfile$ORACLE_SID.ora。# 改参数前执行把 dbs 目录整体备份到独立目录 mkdir -p /home/oracle/backup/dbs_$(date %Y%m%d) cp -rp $ORACLE_HOME/dbs/* /home/oracle/backup/dbs_$(date %Y%m%d)/ # 出问题后执行把备份的 spfile 还原回 dbs 目录 cp /home/oracle/backup/dbs_20250108/spfile$ORACLE_SID.ora $ORACLE_HOME/dbs/spfile$ORACLE_SID.ora-- 还原后正常启动 sqlplus / as sysdba startup;cp -rp保留了文件权限和时间戳这是重点spfile 文件属主必须是 oracle、权限通常是 0644用普通cp覆盖后如果变成 root 属主Oracle 会直接拒绝读取。备份路径用$(date %Y%m%d)生成日期目录是为了让每次备份互不覆盖——万一最近这次备份也带着问题还能往前翻更早的版本。方法三的本质是给改 SGA这种操作上保险不管你把参数调成什么样只要 spfile 原件还在最坏结果就是还原后重新来过。它与方法一并不冲突实际运维中我通常把方法三当习惯把方法一当应急手段每次调参前先备份 dbs出问题先用 pfile 应急拉起实例保住业务再从容研究 spfile 里到底写坏了什么。4.3 三种方法怎么选一张对比表说清楚边界方法前置条件适用场景注意事项方法一pfile 起库 重建 spfile有一份能自洽启动的 pfilespfile 参数组合写坏旧配置仍有效重建前先确认 pfile 内容自洽否则带病生成方法二改 pfile 再启动明确知道哪个参数值不对改动明确比如 target 超 max_size改完必须自查参数间大小关系别改一半方法三备份还原 spfile调参前做过 dbs 备份任何想快速回滚的场景还原后属主、权限要正确备份要放在 dbs 之外选型逻辑很简单追求最快拉起业务用方法一你清楚是哪个参数错用方法二你只想回到改参前的状态用方法三。三个方法都解决让库先起来的问题但都不解决你本来想把 SGA 调成多大的业务问题——库起来之后还要按正确步骤重新调一次 SGA顺序见 5.1。5. 避坑与常见问题改 SGA 前后最容易翻车的五个场景5.1 sga_target 大于 sga_max_size实例带病启动现象改完参数重启startup直接报ORA-00824SGA_TARGET 过大或ORA-00838MEMORY_TARGET 过小实例起不来。 原因sga_target是 ASMM 的目标值sga_max_size是硬上限Oracle 规定目标值不能高于上限。很多人调参时只改sga_target忘了同步sga_max_size或者两个参数在两次 ALTER 里分别改中间某次 shutdown 恰好落在这对矛盾值上。 解决用 pfile 应急启动后按正确顺序改先ALTER SYSTEM SET sga_max_size... SCOPESPFILE再ALTER SYSTEM SET sga_target... SCOPEBOTH最后重启验证。顺序反了第二次 ALTER 可能直接报ORA-02097之类的参数越界错误。5.2 内存值没超物理内存却报 ORA-27102 out of memory现象startup报ORA-27102: out of memory操作系统物理内存明明还有富余。 原因Oracle 在 Linux 上用共享内存段创建 SGA单个段大小受/proc/sys/kernel/shmmax限制。很多服务器默认shmmax只有 32MB 或 64MB你把sga_max_size调到几百 MBshmget直接失败报错信息里的out of memory指的不是物理内存而是共享内存限额。 解决用sysctl调大shmmax并同步调kernel.shmall然后sysctl -p生效或者不依赖内核共享内存改用大页hugepages方式承载 SGA。应急期间可以先临时降低sga_max_size起库保住业务后再慢慢调内核参数不用在生产窗口里硬扛。# 查看当前共享内存上限确认 SGA 是否超限 cat /proc/sys/kernel/shmmax ipcs -lm | grep -i max seg # 临时调大重启失效或写入 /etc/sysctl.conf 永久生效 sysctl -w kernel.shmmax10737418245.3 报了 ORA-00845其实是 /dev/shm 不够现象startup报ORA-00845: MEMORY_TARGET not supported on this system表面看和 SGA 参数无关但确实是调内存参数引发的。 原因11g 起引入自动内存管理AMM用memory_target统一管理 SGA 和 PGAOracle 会把内存映射到/dev/shmtmpfs。/dev/shm默认往往只有物理内存的一半甚至更小memory_target设得比它大就起不来。 解决扩容/dev/shm比如mount -o remount,size2G /dev/shm并写入/etc/fstab让重启后依然生效或者放弃 AMM改用sga_targetpga_aggregate_target的 ASMM 方式管理。要警惕的是很多人把memory_target和sga_target混着改两个管理体系叠加最容易出这种怪报错——先想清楚你到底在用哪套内存管理再动手。5.4 ALTER SYSTEM 改成功了重启后参数又变回原值现象alter system set sga_target2G执行成功show parameter sga也显示 2G但实例一重启又回到旧值。 原因ALTER SYSTEM默认 SCOPEBOTH但静态参数比如sga_max_size只支持 SCOPESPFILE动态参数比如sga_target才支持 BOTH还有一些版本、一些场景下默认行为会有偏差导致修改只落在了当前内存里没有持久化到 spfile。 解决改 SGA 这类参数养成显式写 SCOPE 的习惯。改sga_max_size写SCOPESPFILE改sga_target写SCOPEBOTH改完用show parameter确认再重启验证一次。别嫌麻烦这一步省掉下次翻车的就是你。-- 静态参数只能写 spfile重启生效 ALTER SYSTEM SET sga_max_size2G SCOPESPFILE; -- 动态参数同时写内存和 spfile立即生效并持久化 ALTER SYSTEM SET sga_target2G SCOPEBOTH;5.5 startup pfile 报 ORA-01078 / LRM-00109文件根本没被读到现象startup pfile...后报ORA-01078: failure in processing system parameters或者LRM-00109: could not open parameter file。 原因路径写错、文件名拼错、oracle 用户没有读权限、或者文件放在 oracle 无法访问的目录下。这是 pfile 应急启动里最常见的低级错误属于还没到参数校验就被挡在门外。 解决先用ls -l确认文件存在且权限是 oracle 可读再用cat确认文件内容确实是参数文本最后在启动命令里写绝对路径。注意 pfile 文件名必须以init开头文件内容必须是parametervalue格式逐行排列。先保证文件能打开再谈参数对不对——这个顺序别搞反。6. 快速定位改完 SGA 起不来按这三步往下查6.1 第一步看报错发生在启动的哪个阶段拿到启动失败的现场先别看参数看错误发生在哪一秒。实例启动分 NOMOUNT分配 SGA、MOUNT读控制文件、OPEN读数据文件三个阶段SGA 相关错误一定发生在第一阶段。特征是startup命令发出后立刻报错、Total System Global Area还没打印出来。如果 SGA 大小已经打印、库卡在装载或打开阶段那是控制文件或数据文件的问题与 SGA 无关别在这篇文章里找答案直接去看告警日志里的文件路径信息。6.2 第二步确认实例读的是 pfile 还是 spfile在 dbs 目录下执行ls -l $ORACLE_HOME/dbs/spfile*看有没有spfile$SID.ora。有且你没指定 pfile那实例读的就是它——问题九成在 spfile 的参数组合没有实例才读init$SID.ora或默认init.ora。连入实例后show parameters spfile这一行有值就代表当前用的是 spfile。这个确认动作决定了该用方法一还是方法二spfile 出问题走方法一pfile 本身参数错走方法二。6.3 第三步对照三个硬约束做参数体检把目标参数和系统限额对齐两条命令五秒钟查完# 看系统共享内存上限与 /dev/shm 大小 ipcs -lm df -h /dev/shm-- 看参数文件里的内存配置是否自洽 SELECT name, value FROM v$parameter WHERE name IN (sga_max_size,sga_target,memory_target,memory_max_target);对照三个约束判断一是sga_target ≤ sga_max_size二是sga_max_size加 PGApga_aggregate_target不超过物理内存的可用余量三是sga_max_size不超过内核shmmax用大页或 AMM 的场景分别对应大页总量和/dev/shm大小。三条都满足还起不来再回头怀疑组件参数db_cache_size、shared_pool_size之和是否越界。从那以后我每次动 SGA 之前都强制走一遍固定流程先备份 dbs 目录、再create pfile from spfile留文本快照、最后把目标参数写成一张sga_max_size/sga_target/ 系统余量的对照表才动手。备份五分钟排查两小时——这笔账算过太多次了。希望这篇笔记能帮你少踩一次这个坑。本文还有配套的精品资源点击获取