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 小时前
力扣574-当选者
leetcode·oracle·数据库开发
AI浩1 小时前
【Redis】Windows下Redis环境搭建与使用详细教程
数据库·windows·redis
卿雪1 小时前
认识Redis:Redis 是什么?好处?业务场景?和MySQL的区别?
服务器·开发语言·数据库·redis·mysql·缓存·golang
JIngJaneIL1 小时前
基于Java失物招领系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·vue
爱尔兰极光1 小时前
数据库基本操作(下)
数据库·sql
kka杰1 小时前
MYSQL-索引
数据库·mysql
Aze..2 小时前
PVE安装 Ubuntu 服务器版
运维·服务器·数据库
他们叫我技术总监2 小时前
ORA-14402: 更新分区关键字列将导致分区的更改,多种解决方案
oracle·ora-14402
Boilermaker19922 小时前
[MySQL] 事务的隔离性与 MVCC
数据库·mysql