Oracle数据库的内存管理经历了从手动管理到自动管理的演进过程。在10g时代,DBA需要分别设置SGA_TARGET和PGA_AGGREGATE_TARGET来管理SGA和PGA,而到了11g,Oracle引入了MEMORY_TARGET参数,将SGA和PGA纳入统一的内存池中由数据库自动调配。这种全自动内存管理方式(AMM,Automatic Memory Management)大大简化了内存配置工作,但也带来了不少新的问题,比如Linux下常见的ORA-00845错误、内存频繁交换导致性能抖动等。要正确使用MEMORY_TARGET,就必须理解它背后的实现机制和适用边界。

一、MEMORY_TARGET的工作原理
MEMORY_TARGET表示Oracle实例可以使用的总内存上限,Oracle会在SGA和PGA之间动态分配这部分内存。当系统中PGA的并发需求增大时,数据库可以自动缩减SGA中某些组件的内存,把释放出来的空间划给PGA使用;反之,当PGA需求下降时,内存又会回流到SGA。这种动态调整依赖于几个后台进程的协作,其中MMAN(Memory Manager)进程每隔几分钟会评估当前的内存压力情况,并决定是否需要在SGA与PGA之间转移内存。
当设置MEMORY_TARGET为非零值时,如果SGA_TARGET和PGA_AGGREGATE_TARGET没有显式设置,它们会被自动置为零,表示完全交给Oracle自动管理。如果同时设置了这三个参数,那么SGA_TARGET和PGA_AGGREGATE_TARGET的值会被视为各自治约下限参考,Oracle会优先保证它们的最小需求,剩余部分灵活调配。这一点可以通过查询V$MEMORY_DYNAMIC_COMPONENTS视图来观察,该视图记录了各个内存组件当前的分配情况和最近一次调整的历史。
需要特别注意的是,MEMORY_TARGET的自动调整是针对SGA整体和PGA整体之间的转移,SGA内部各组件(如buffer cache、shared pool)的自动调整则沿用了10g的ASMM机制。也就是说AMM是在ASMM之上再叠加了一层SGA与PGA之间的调度。理解这个层次关系,对后面分析性能问题很有帮助。
查看当前内存配置的常用语句如下:
-- 查看当前内存参数设置
SHOW PARAMETER memory_target;
SHOW PARAMETER sga_target;
SHOW PARAMETER pga_aggregate_target;
-- 查看内存组件的动态调整建议
SELECT component, current_size/1024/1024 AS cur_mb,
min_size/1024/1024 AS min_mb,
max_size/1024/1024 AS max_mb
FROM v$memory_dynamic_components;
-- 查看内存调整操作历史
SELECT parameter, initial_size/1024/1024 AS init_mb,
final_size/1024/1024 AS final_mb, status
FROM v$memory_resize_operations
ORDER BY update_time DESC;二、MEMORY_TARGET与SGA_TARGET、PGA_AGGREGATE_TARGET的关系
这三个参数之间存在明确的优先级和约束规则。简单来说可以分为三种配置场景:第一种是只设置MEMORY_TARGET,SGA_TARGET和PGA_AGGREGATE_TARGET均为零,这是完全自动管理,SGA和PGA的边界完全由Oracle根据负载自动决定;第二种是三者都设置,此时MEMORY_TARGET仍然是总上限,SGA_TARGET和PGA_AGGREGATE_TARGET作为下限,Oracle保证SGA至少有SGA_TARGET指定的内存,PGA至少有PGA_AGGREGATE_TARGET指定的内存,但不能突破MEMORY_TARGET的总盘子;第三种是MEMORY_TARGET为零,仅设置SGA_TARGET,这就退回到了10g的ASMM加手动PGA模式。
与MEMORY_TARGET配套的还有MEMORY_MAX_TARGET参数。MEMORY_TARGET是动态参数,可以在数据库运行时通过ALTER SYSTEM调整,但不能超过MEMORY_MAX_TARGET设定的值。MEMORY_MAX_TARGET是静态参数,修改后需要重启实例才能生效。一个常见的规划做法是把MEMORY_MAX_TARGET设置得比MEMORY_TARGET略大一些,比如MEMORY_TARGET设为20G,MEMORY_MAX_TARGET设为24G,给后续扩容留出余地,避免临时需要扩内存时还要走重启流程。
配置示例及各参数的约束关系演示:
-- 方式一:使用spfile在线调整(推荐) ALTER SYSTEM SET memory_max_target=24G SCOPE=SPFILE; ALTER SYSTEM SET memory_target=20G SCOPE=BOTH; ALTER SYSTEM SET sga_target=8G SCOPE=BOTH; ALTER SYSTEM SET pga_aggregate_target=4G SCOPE=BOTH; -- 注意:sga_target + pga_aggregate_target -- 必须小于等于 memory_target,否则启动时会报错 -- 方式二:只修改pfile后重启 -- 在init.ora文件中加入: -- memory_max_target=24G -- memory_target=20G
在实际规划时,总内存的分配建议遵循这样一个经验公式:操作系统和相关进程预留20%左右,剩余的80%交给Oracle,其中MEMORY_TARGET就是这个80%的值。如果服务器是数据库专用机,这个比例可以适当放宽,但如果服务器上还跑着应用或其他中间件,就必须给OS留足空间,否则容易出现swap交换,反而拖垮整个数据库。
三、Linux下ORA-00845错误的排查与解决
使用AMM时最经典的问题就是启动数据库时报ORA-00845错误:MEMORY_TARGET not supported on this system。这个错误的根本原因是AMM在Linux上依赖POSIX共享内存,具体是通过/dev/shm这个tmpfs文件系统来实现的。Oracle会在/dev/shm中创建内存映射文件,如果/dev/shm的大小小于MEMORY_TARGET(或MEMORY_MAX_TARGET),实例就无法启动。
很多Linux发行版默认将/dev/shm设置为物理内存的一半,比如一台64G内存的服务器,/dev/shm默认只有32G,如果你把MEMORY_TARGET设成了40G,启动时就会报ORA-00845。排查方法很简单,直接用df -h查看/dev/shm的挂载大小即可。解决方式有两种:一种是临时修改,用mount命令重新挂载;另一种是永久修改/etc/fstab。需要注意的是/dev/shm的大小不能超过物理内存总量,设置过大时要警惕其他程序也在使用tmpfs的场景。
# 查看当前/dev/shm大小 df -h /dev/shm # 临时扩大/dev/shm到48G(重启后失效) mount -o remount,size=48G /dev/shm # 永久生效:编辑/etc/fstab,加入或修改如下行 # tmpfs /dev/shm tmpfs defaults,size=48G 0 0 # 修改后重新挂载 mount -o remount /dev/shm
除了空间大小问题,还有一个容易被忽略的坑:如果/dev/shm中残留了上次异常关闭的Oracle内存映射文件(文件名类似ora_
四、AMM是否适合生产环境:与ASMM的选择建议
AMM虽然方便,但并不是所有场景下的最优选择。在Linux平台下,AMM使用共享内存文件映射的方式会禁用大页(HugePages),而大页对于SGA较大(一般超过8G到16G)的数据库来说非常重要,它能够显著减少页表占用的内存和TLB miss,降低CPU开销。因此对于SGA较大的核心生产库,很多DBA会选择关闭AMM(设置MEMORY_TARGET为零),改用SGA_TARGET加PGA_AGGREGATE_TARGET的ASMM方式,同时在操作系统层配置大页内存。这也是Oracle官方在部分场景下的建议。
判断是否应该用AMM可以参考几个条件:数据库服务器内存规模不大(比如32G以下)、SGA没有配置大页、希望简化运维减少手动调参的工作量,这类场景AMM是合适的。反之,如果是内存几百G的大型数据库、已经启用了HugePages、或者负载类型非常稳定(内存需求波动小,自动调整带来的收益有限),那么ASMM加手动规划会带来更稳定的性能表现。此外在Exadata等一体机上,通常也有各自的内存管理最佳实践,需按官方文档执行。
如果决定从AMM切换回ASMM,操作步骤如下:
-- 关闭AMM,切换回ASMM ALTER SYSTEM SET memory_target=0 SCOPE=SPFILE; ALTER SYSTEM SET memory_max_target=0 SCOPE=SPFILE; ALTER SYSTEM SET sga_target=16G SCOPE=SPFILE; ALTER SYSTEM SET sga_max_size=16G SCOPE=SPFILE; ALTER SYSTEM SET pga_aggregate_target=6G SCOPE=SPFILE; -- 上述均为静态调整方式,需要重启实例 SHUTDOWN IMMEDIATE; STARTUP;
切换之后记得在操作系统层配置大页。可以通过查询/proc/meminfo中的HugePages_Total、HugePages_Free确认大页配置情况,并确保Oracle用户的memlock限制足够大,否则实例启动申请大页时会失败。对于PGA部分,虽然设置了PGA_AGGREGATE_TARGET,但也要明白它只是一个目标值而非硬限制,个别会话的PGA在排序、哈希等操作密集时仍可能超出,这一点在容量规划时要留有冗余。
总的来说,MEMORY_TARGET提供了一种省心的内存管理方式,适合中小规模或者运维人力有限的场景。但在使用前务必确认/dev/shm的配置,运行中关注V$MEMORY_DYNAMIC_COMPONENTS的调整记录,避免SGA和PGA之间频繁的大规模内存转移造成性能波动。对于大内存的关键业务库,ASMM加大页的组合依然是更稳妥的选择。掌握这两套机制的原理和边界,才能根据实际的硬件条件和业务特点做出合理的内存管理决策。
MEMORY_TARGETOracle自动内存管理SGA和PGA修改时间:2026-09-03 12:55:36