在 Oracle 数据库的日常运维中,DBA 可能会在启动数据库实例时遭遇 ORA-00845: MEMORY_TARGET not supported on this system 的错误。
这个错误直接指向 Oracle 11g 引入的自动内存管理(AMM)功能与当前操作系统环境配置之间的冲突。
本文将深入剖析该错误产生的原因,通过实验复现问题,并提供详尽的解决方案。
01
问题分析:ORA-00845 的根源
ORA-00845 错误的核心原因在于 Oracle 的自动内存管理(Automatic Memory Management, AMM)与 Linux 操作系统的共享内存文件系统 /dev/shm 之间的配置不匹配。
自动内存管理 (AMM)
当您在 Oracle 中设置了 MEMORY_TARGET 或 MEMORY_MAX_TARGET 参数后,即启用了 AMM。
在此模式下,Oracle 实例会统一管理系统全局区(SGA)和程序全局区(PGA)的总内存,并根据负载动态调整它们各自的大小。
共享内存文件系统 (/dev/shm)
在 Linux 系统上,AMM 功能依赖于 /dev/shm 这个基于内存的临时文件系统(tmpfs)来实现 SGA 和 PGA 的管理。
Oracle 会在 /dev/shm 中创建文件来分配所需的共享内存。
根本原因
如果 MEMORY_TARGET 或 MEMORY_MAX_TARGET 参数所设定的值大于操作系统为 /dev/shm 分配的可用空间,Oracle 实例在启动时将无法申请到足够的内存,从而导致启动失败并抛出 ORA-00845 错误。
其他可能原因
- HugePages 冲突
在 Linux 系统中,如果配置并启用了 HugePages,它与 AMM 是不兼容的。
HugePages 使用另一种内存管理机制,而 AMM 必须使用 /dev/shm。
02
实验复现
为了直观地理解该问题,我们进行一次故障复现实验。
实验环境
- 操作系统
Red Hat Enterprise Linux release 8.8 (Ootpa)
- 数据库版本
Oracle Database 19c
- 初始状态
数据库正常运行
1
步骤 1: 检查初始状态
首先,以 root 用户检查当前 /dev/shm 的大小。
[root@localhost ~]# df -h | grep shm
tmpfs 834M 1.1M 833M 1% /dev/shm
当前 /dev/shm 的大小为 834M 。
然后,以 oracle 用户登录数据库,查看当前的 MEMORY_TARGET 设置。
SQL> show parameter memory_target;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
memory_target big integer 800M
当前 memory_target 为 800M,小于 834M ,因此数据库可以正常启动。
2
步骤 2: 制造错误条件
现在,我们将 MEMORY_TARGET 的值调高至1444m,使其超过 /dev/shm 的 834M 限制。
SQL> alter system set memory_target=1444m scope=spfile;
System altered.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
3
步骤 3: 触发错误
尝试重新启动数据库。
SQL> startup
ORA-00845: MEMORY_TARGET not supported on this system
错误成功复现。
这验证了当 MEMORY_TARGET 大于 /dev/shm 时,数据库将无法启动。
03
解决方案与验证
针对此问题,有多种解决方案,DBA 可根据实际环境和权限选择最合适的一种。
方案一:扩大 /dev/shm 的大小(推荐)
这是最直接且最推荐的解决方案,因为它允许您继续使用便捷的自动内存管理功能。
1
临时扩大 (立即生效,重启失效)
以 root 用户执行以下命令,将 /dev/shm 的大小调整为 2GB(应大于新的 MEMORY_TARGET 值)。
[root@anyadb2 ~]# mount -o remount,size=2G /dev/shm
再次检查大小,确认修改已生效。
[root@anyadb2 ~]# df -h | grep shm
tmpfs 2.0G 1.1M 2.0G 1% /dev/shm
2
验证
现在,以 oracle 用户重新启动数据库。
SQL> startup
ORACLE instance started.
Total System Global Area 1526723608 bytes
Fixed Size 30368792 bytes
Variable Size 1207959552 bytes
Database Buffers 268435456 bytes
Redo Buffers 19959808 bytes
Database mounted.
数据库成功启动,问题解决。
3
永久生效 (推荐)
为了让此更改在系统重启后依然有效,需要修改 /etc/fstab 文件。以 root 用户编辑该文件:
[root@anyadb2 ~]# vi /etc/fstab
找到包含 /dev/shm 的行,修改或添加如下内容,将 size 设置为期望的值。
tmpfs /dev/shm tmpfs defaults,size=2G 0 0
保存文件后,此配置将在下次系统重启时自动生效。
方案二:减小 MEMORY_TARGET 参数
如果无法修改操作系统配置(例如,物理内存有限或无 root 权限),则可以降低 Oracle 的内存需求。
由于数据库无法启动,需要通过 pfile(文本参数文件)进行操作。
1
从 spfile 创建 pfile
-- 在 SQL*Plus 中,即使实例未启动也可以执行
SQL> create pfile='/tmp/initTEMP.ora' from spfile;
File created.
2
编辑 pfile
使用文本编辑器打开 /tmp/initTEMP.ora,找到 memory_target 参数并将其值减小到小于 /dev/shm 的大小(例如,800MB)。
[root@anyadb1 ~]# cat /tmp/init_temp.ora | grep memory_target
*.memory_target=800m
3
使用 pfile 启动数据库
SQL> startup pfile='/tmp/init_temp.ora'
ORACLE instance started.
Total System Global Area 838858904 bytes
Fixed Size 30374040 bytes
Variable Size 608174080 bytes
Database Buffers 192937984 bytes
Redo Buffers 7372800 bytes
Database mounted.
Database opened.
4
重建 spfile 并正常重启
数据库成功启动后,根据修改后的 pfile 重新创建 spfile,然后正常重启。
SQL> create spfile from pfile='/tmp/initTEMP.ora';
File created.
SQL> shutdown immediate;
SQL> startup;
方案三:禁用 AMM,切换至 ASMM
在某些特定场景下,例如需要启用 HugePages 以提升大型 SGA 性能时,必须禁用 AMM。
此时应切换到自动共享内存管理(Automatic Shared Memory Management, ASMM)。
该过程与方案二类似:
-
创建并编辑 pfile。
-
在 pfile 中,将 memory_target 和 memory_max_target 参数设置为 0 或直接注释掉。
3)设置 ASMM 相关参数,例如:
[root@anyadb2 ~]# grep -E "sga|pga|mem" /tmp/init_temp.ora
#*.memory_target=800m
*.sga_target=1G
*.pga_aggregate_target=600m
4)使用修改后的 pfile 启动数据库,然后重建 spfile 并正常重启。
SQL> startup pfile='/tmp/init_temp.ora'
ORACLE instance started.
Total System Global Area 1073738528 bytes
Fixed Size 30376736 bytes
Variable Size 603979776 bytes
Database Buffers 432013312 bytes
Redo Buffers 7368704 bytes
Database mounted.
Database opened.
04
总结
ORA-00845 是一个典型的 Oracle 配置与操作系统资源限制冲突的案例。
其根本原因在于为自动内存管理(AMM)设置的 MEMORY_TARGET 超出了 Linux 系统 /dev/shm 文件系统的大小。
最常用且推荐的解决方法是作为 root 用户调大 /dev/shm 的挂载空间并将其配置持久化。
在无法调整系统环境时,通过 pfile 降低数据库内存参数或切换到 ASMM 也是可行的备选方案。
理解 Oracle 内存管理机制与操作系统底层资源的交互关系,是 DBA 高效排错和性能优化的关键。
写在最后
实际上,多数数据库性能问题的根源,常常与操作系统层面的资源配置、性能瓶颈等因素密切相关。
如果你还想系统补齐 Linux 的实战短板,推荐看看刘峰老师的 Linux 系列课程,循序渐进,从命令行到运维部署,一步到位。