Oracle修改完sga、pga启动失败处理方案

背景:Oracle数据库宕机,查看linux系统日志,发现是内存溢出

powershell 复制代码
# 1. 搜索数据库宕机时间附近的"OOM"(内存溢出,数据库进程被Kill)
grep -i "oom\|kill" /var/log/messages | grep -i "oracle"
# 解释:若输出类似"Killed process 1234 (oracle) score 500",说明Oracle进程因内存不足被系统终止

# 2. 搜索"ora_"开头的Oracle后台进程异常(如崩溃、被终止)
grep -i "ora_" /var/log/messages | grep -i "error\|abort\|crash"

# 3. 排查磁盘空间满(Oracle数据文件/日志文件无法写入导致宕机)
grep -i "no space left on device" /var/log/messages

# 4. 排查系统是否意外重启(数据库随系统宕机)
grep -i "reboot\|shutdown" /var/log/messages
# 或查看系统启动记录(确认是否重启)
last reboot | head -5

# 5. 按时间范围筛选(假设宕机时间是2025-11-27 14:00左右)
sed -n '/Nov 27 14:/,/Nov 27 15:/p' /var/log/messages

查到的错误:

powershell 复制代码
grep -i "oom\|kill" /var/log/messages | grep -i "oracle"
Nov 27 09:37:50 db kernel: oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=oracle,pid=3906,uid=54321
Nov 27 09:37:50 db kernel: Out of memory: Killed process 3906 (oracle) total-vm:13385668kB, anon-rss:1440kB, file-rss:2804kB, shmem-rss:6395864kB, UID:54321 pgtables:15496kB oom_score_adj:0
Nov 27 09:37:50 db kernel: oom_reaper: reaped process 3906 (oracle), now anon-rss:0kB, file-rss:0kB, shmem-rss:6395860kB

从日志可以明确判断:Oracle 数据库进程(PID=3906,用户 UID=54321)因系统内存溢出(OOM,Out of Memory)被 Linux 内核强制终止,导致数据库宕机!
日志关键信息解读

日志字段 含义说明
oom-kill 内核触发 OOM killer(内存溢出杀手)机制,用于释放内存避免系统崩溃
task=oracle,pid=3906 被终止的进程是oracle用户的进程,PID=3906(Oracle 后台进程 / 会话进程)
total-vm:13385668kB 该 Oracle 进程申请的虚拟内存总量(约 12.8GB)
shmem-rss:6395864kB 共享内存占用(约 6.1GB,大概率是 Oracle 的 SGA 共享内存段)
Out of memory: Killed process 核心原因:系统物理内存 + 交换分区耗尽,内核选择占用内存较多的 Oracle 进程终止

处理步骤(先恢复数据库,再解决内存问题)

  1. 先检查系统当前内存状态(避免重启后再次 OOM)
shell 复制代码
# 查看内存/交换分区使用情况
free -h
# 查看交换分区是否启用(若Swap为0,系统无缓冲空间,容易OOM)
swapon --show

若剩余内存仍不足(如available < 2GB),扩容临时交换分区:

shell 复制代码
# 临时创建4GB交换文件(避免重启后失效)
dd if=/dev/zero of=/tmp/swapfile bs=1G count=4
chmod 600 /tmp/swapfile
mkswap /tmp/swapfile
swapon /tmp/swapfile
  1. 重启 Oracle 数据库
shell 复制代码
# 切换到oracle用户
su - oracle

# 检查数据库实例状态
sqlplus / as sysdba << EOF
select instance_name, status from v\$instance;
EOF

# 若状态为DOWN/UNKNOWN,启动数据库
sqlplus / as sysdba << EOF
startup;  # 正常启动(若有数据文件损坏,会提示ORA错误,需进一步处理)
# 若启动失败,查看告警日志定位问题
show parameter background_dump_dest;  # 确认告警日志路径
EOF

# 启动后验证监听是否正常(确保客户端能连接)
lsnrctl status
# 若监听未启动,启动监听
lsnrctl start

根本解决:避免再次因 OOM 导致数据库宕机

核心思路:要么减少内存占用,要么增加物理内存 / 交换分区,要么优化 Oracle 内存配置

  1. 优化 Oracle 内存配置(最直接有效)
    Oracle 的内存占用主要来自 SGA(系统全局区) 和 PGA(程序全局区),默认配置可能超过系统实际内存容量,需调整:
powershell 复制代码
# 1. 查看当前Oracle内存配置(登录SQL*Plus)
su - oracle
sqlplus / as sysdba << EOF
show parameter sga_target;    # SGA目标值(默认可能过大)
show parameter pga_aggregate_target;  # PGA目标值
show parameter memory_target; # 总内存目标(若启用自动内存管理)
EOF

调整原则:SGA + PGA ≤ 系统物理内存的 80%

建议:SGA=内存的80%*80% PGA=内存的80%*20%

shell 复制代码
-- 1. 先关闭自动内存管理(若之前启用)
alter system set memory_target=0 scope=spfile;
alter system set memory_max_target=0 scope=spfile;

-- 2. 配置SGA和PGA(根据服务器实际情况调整,此处为32GB内存推荐值)
alter system set sga_target=16G scope=spfile;
alter system set sga_max_size=16G scope=spfile;  # SGA上限,建议与sga_target一致
alter system set pga_aggregate_target=6G scope=spfile;

-- 3. 重启数据库生效
shutdown immediate;
startup;

-- 4. 验证配置是否生效
show parameter sga_target;
show parameter pga_aggregate_target;
  1. 增加系统物理内存或交换分区(长期解决方案)
    若优化 Oracle 内存后仍频繁 OOM,说明系统物理内存不足(如数据库服务器仅 8GB 内存,却运行大型 Oracle 实例),需:
    1.升级物理内存(优先选择,性能最佳);
    2.配置永久交换分区(避免临时交换文件重启后失效):
powershell 复制代码
# 创建4GB永久交换分区
dd if=/dev/zero of=/swapfile bs=1G count=4
chmod 600 /swapfile
mkswap /swapfile
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab  # 开机自动挂载
swapon /swapfile  # 立即生效

Oracle官方建议swap设置标准

  • RAM为1-2GB时,SWAP大小建议为RAM大小的1.5倍
  • RAM为2-16GB时,SWAP大小建议与RAM大小相等
  • RAM大于16GB时,SWAP大小建议为16GB

本次修改完sga、pga后启动失败问题

重启数据库报错:

ORA-00843: Parameter not taking MEMORY_MAX_TARGET into account

ORA-00849: SGA_TARGET 21474836480 cannot be set to more than MEMORY_MAX_TARGET 0.

这个错误的核心原因是:你同时启用了「手动内存配置(SGA_TARGET)」和「自动内存管理(MEMORY_MAX_TARGET=0)」,两者冲突------Oracle 中若设置 MEMORY_MAX_TARGET=0(禁用自动内存管理),则 SGA_TARGET 不能独立设置为非零值(必须依赖 MEMORY_MAX_TARGET 作为总内存上限)。

已经关闭自动内存管理,重启数据库报该错误,无法启动,无法进行修改sga、pga配置, 以下是强制清除冲突参数 + 重新配置 的方案

步骤 1:直接手动创建 pfile(无需依赖旧 spfile)

powershell 复制代码
su - oracle

# 1. 用vi创建临时pfile(路径:/tmp/initorcl.ora,实例名按你的实际情况改,如orcl、prod等)
vi /tmp/initorcl.ora

关键:在 pfile 中写入核心配置(仅保留必要参数)

将以下内容复制到/tmp/initorcl.ora(替换orcl为你的数据库实例名,比如实例名是prod,就把所有orcl.改成prod.):

powershell 复制代码
# 实例名(必须与你的实际实例名一致,否则启动失败)
orcl.instance_name=orcl

# 内存配置(纯手动模式,无冲突)
orcl.sga_max_size=16G
orcl.sga_target=16G
orcl.pga_aggregate_target=6G

# 控制文件路径(关键!必须填写你数据库的控制文件实际路径,否则启动失败)
# 👉 重点:替换以下路径为你服务器上的控制文件路径(通常在$ORACLE_BASE/oradata/<实例名>/下),有几个control_files就写几个
orcl.control_files='/u01/app/oracle/oradata/orcl/control01.ctl','/u01/app/oracle/oradata/orcl/control02.ctl'

# 字符集(默认UTF8,若你的数据库是其他字符集,可修改,如ZHS16GBK)
orcl.nls_characterset=UTF8

步骤 2:用手动创建的 pfile 启动数据库

powershell 复制代码
# 登录SQL*Plus(即使数据库未启动,也能登录)
sqlplus / as sysdba

# 用临时pfile启动数据库(路径是你刚才创建的/tmp/initorcl.ora)
startup pfile='/tmp/initorcl.ora';

报错:

powershell 复制代码
startup pfile='/tmp/initorcl.ora';
ORACLE instance started.

Total System Global Area 1.7103E+10 bytes
Fixed Size                  2270360 bytes
Variable Size            2315258728 bytes
Database Buffers         1.4764E+10 bytes
Redo Buffers               21684224 bytes
ORA-00205: error in identifying control file, check alert log for more info

原因:control_files只有1个,pfile里写了两个,导致找不到第2个,删掉第2个

报错:

powershell 复制代码
startup pfile='/tmp/initorcl.ora';
ORACLE instance started.

Total System Global Area 1.7103E+10 bytes
Fixed Size                  2270360 bytes
Variable Size            2315258728 bytes
Database Buffers         1.4764E+10 bytes
Redo Buffers               21684224 bytes
ORA-00201: control file version 11.2.0.4.0 incompatible with ORACLE version
11.2.0.0.0

控制文件的版本(11.2.0.4.0)高于当前 Oracle 数据库软件的版本(11.2.0.0.0),版本不匹配导致无法识别控制文件,但是数据库就是11.2.0.4.0

解决思路:修正 Oracle 环境变量,确保实例启动时加载的是 11.2.0.4 版本的软件

步骤 1:验证当前 Oracle 环境变量

powershell 复制代码
su - oracle

# 1. 查看ORACLE_HOME(必须指向11.2.0.4的安装目录,不能是11.2.0.0)
echo $ORACLE_HOME
# 正确输出示例:/u01/app/oracle/product/11.2.0.4/dbhome_1
# 错误输出示例:/u01/app/oracle/product/11.2.0/dbhome_1(无.4,指向旧版本)

# 2. 查看ORACLE_SID(确保与数据库实例名一致)
echo $ORACLE_SID  # 输出示例:orcl(需与pfile中的db_name一致)

# 3. 验证Oracle软件实际版本(确认安装的是11.2.0.4)
$ORACLE_HOME/bin/sqlplus -V
# 正确输出示例:SQL*Plus: Release 11.2.0.4.0 Production(显示11.2.0.4)
# 错误输出示例:SQL*Plus: Release 11.2.0.0.0 Production(显示11.2.0.0,说明ORACLE_HOME指向错误)

步骤 2:修正环境变量(指向 11.2.0.4 版本)

powershell 复制代码
# 1. 编辑oracle用户的环境变量配置文件(永久生效)
vi ~/.bash_profile  # 或 ~/.bashrc(不同系统默认文件可能不同)

# 2. 确保文件中包含以下正确配置(替换为你的11.2.0.4安装路径)
export ORACLE_HOME=/u01/app/oracle/product/11.2.0.4/dbhome_1  # 关键:指向11.2.0.4目录
export ORACLE_SID=orcl  # 你的实例名(与pfile中db_name一致)
export PATH=$ORACLE_HOME/bin:$PATH  # 优先加载11.2.0.4的bin目录

# 3. 保存退出,生效环境变量
source ~/.bash_profile  # 或 source ~/.bashrc

# 4. 验证修正结果(必须显示11.2.0.4)
sqlplus -V
# 输出:SQL*Plus: Release 11.2.0.4.0 Production → 修正成功

步骤 3:重新启动数据库

powershell 复制代码
# 1. 登录SQL*Plus(此时加载的是11.2.0.4版本)
sqlplus / as sysdba

# 2. 关闭之前启动的实例(nomount状态)
shutdown abort;

# 3. 用正确的pfile启动(控制文件路径已确认正确)
startup pfile='/tmp/initorcl.ora';

版本已经是对的了,启动还是报错!!!

解决思路:在 pfile 中添加 COMPATIBLE=11.2.0.4.0 参数(与软件版本、控制文件版本一致),彻底统一版本配置,步骤如下:

步骤 1:更新 pfile(添加 COMPATIBLE 参数,统一版本)

powershell 复制代码
su - oracle

# 1. 删除旧pfile,重新创建(确保参数完整无错误)
rm -f /tmp/initorcl.ora

# 2. 逐行写入新pfile(替换3个关键信息,其他参数不变)
#    👉 1) 实例名:替换为你的$ORACLE_SID(如orcl)
#    👉 2) 控制文件路径:替换为你搜索到的真实路径
#    👉 3) COMPATIBLE=11.2.0.4.0(必须与软件/控制文件版本一致)
echo 'orcl.db_name=orcl' >> /tmp/initorcl.ora
echo 'orcl.sga_max_size=16G' >> /tmp/initorcl.ora
echo 'orcl.sga_target=16G' >> /tmp/initorcl.ora
echo 'orcl.pga_aggregate_target=6G' >> /tmp/initorcl.ora
echo 'orcl.compatible=11.2.0.4.0' >> /tmp/initorcl.ora  # 核心:添加兼容参数
echo "orcl.control_files='/u01/app/oracle/oradata/orcl/control01.ctl','/u01/app/oracle/fast_recovery_area/orcl/control02.ctl'" >> /tmp/initorcl.ora

关键说明:

COMPATIBLE 参数的作用:控制数据库支持的功能和数据格式,其值必须 ≤ 软件版本、≥ 控制文件版本;

你的场景中,软件版本 = 11.2.0.4.0,控制文件版本 = 11.2.0.4.0,因此 COMPATIBLE 必须设为 11.2.0.4.0(三者一致)。

步骤 2:验证 pfile 参数(确保无拼写错误)

powershell 复制代码
# 查看pfile内容,确认COMPATIBLE参数正确
cat /tmp/initorcl.ora
# 输出应包含:orcl.compatible=11.2.0.4.0(无拼写错误,版本号正确)

步骤 3:启动数据库(版本一致,必成功)

powershell 复制代码
sqlplus / as sysdba

# 1. 关闭之前启动的nomount状态实例
shutdown abort;

# 2. 用更新后的pfile启动(所有版本一致,控制文件可正常识别)
startup pfile='/tmp/initorcl.ora';

启动成功

步骤 4:重建 spfile(永久生效,彻底解决)

数据库成功启动后,立即重建 spfile,让 COMPATIBLE 参数和内存配置永久生效:

powershell 复制代码
# 基于正确的pfile生成新spfile
create spfile from pfile='/tmp/initorcl.ora';

# 验证spfile参数(确认COMPATIBLE已生效)
show parameter compatible;  # 应显示 11.2.0.4.0

# 重启数据库,确认无需指定pfile也能正常启动
shutdown immediate;
startup;  # 直接启动,无任何报错

# 最终验证所有核心参数
show parameter db_name;         # 与ORACLE_SID一致
show parameter compatible;      # 11.2.0.4.0
show parameter sga_max_size;    # 16G
show parameter pga_aggregate_target;  # 6G
select instance_name, status from v$instance;  # 状态为OPEN

步骤 5:清理临时文件

powershell 复制代码
rm -f /tmp/initorcl.ora  # 临时pfile已无用
相关推荐
小陈工1 天前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
科技小花1 天前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸1 天前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain1 天前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希1 天前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神1 天前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员1 天前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java1 天前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿1 天前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴1 天前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存