在使用Oracle 11g及以后版本时,很多DBA都会接触到MEMORY_TARGET和MEMORY_MAX_TARGET这对参数。它们是Oracle自动内存管理(AMM,Automatic Memory Management)的入口,由Oracle自动在SGA和PGA之间调配内存资源。其中MEMORY_MAX_TARGET定义了整个数据库实例能够使用的内存总量上限,而MEMORY_TARGET则是当前生效的实际目标值。前者相当于天花板,后者相当于当前水位。理解这两个参数的上限约束条件,对避免ORA-00845、ORA-4031等经典报错非常关键。

一、MEMORY_MAX_TARGET与MEMORY_TARGET的关系
这两个参数是一对搭档。MEMORY_MAX_TARGET是静态参数,修改后需要重启实例才能生效;MEMORY_TARGET是动态参数,可以在数据库运行期间在线调整,但其取值不能超过MEMORY_MAX_TARGET。换句话说,你可以先把天花板设高一点,然后根据实际负载情况灵活调整水位线,而不需要频繁重启数据库。
如果只设置了MEMORY_TARGET而没有显式设置MEMORY_MAX_TARGET,Oracle会自动将MEMORY_MAX_TARGET取值为MEMORY_TARGET的值。反之,如果只设置MEMORY_MAX_TARGET而不设置MEMORY_TARGET,实例启动后MEMORY_TARGET默认为0,此时数据库退回到传统的手工内存管理模式,需要分别配置SGA_TARGET和PGA_AGGREGATE_TARGET。
需要注意的是,当启用AMM后,如果用户又手工指定了SGA_TARGET或PGA_AGGREGATE_TARGET,这两个值会被视为对应组件的最小需求值,Oracle会在自动分配时保证不低于这个下限。这种混合配置在迁移过渡期比较常见,但长期运行的生产库建议明确统一到一种管理模式,避免参数之间互相牵制导致内存调配失灵。
二、上限受哪些因素约束
MEMORY_MAX_TARGET的绝对上限并不是随意定的,它受到多个层面的约束。第一层是操作系统物理内存。一般建议MEMORY_TARGET加上操作系统自身开销、以及其他进程的内存需求之后,总量不要超过物理内存的70%到80%,给文件系统缓存和系统进程留出余量。如果是与其他应用混部署的服务器,这个比例还要进一步压缩。
第二层约束在Linux平台上尤为典型,就是共享内存文件系统/dev/shm的大小。Oracle在Linux上启用AMM时,会将SGA创建在/dev/shm下的内存映射文件中,因此MEMORY_MAX_TARGET不能超过/dev/shm的可用大小,否则启动时会报ORA-00845错误,提示MEMORY_TARGET not supported on this operating system or automatic memory management disabled。查看和调整的方法如下:
# 查看当前 /dev/shm 大小 df -h /dev/shm # 临时重设为 16G(重启失效) mount -o remount,size=16G /dev/shm # 永久生效:编辑 /etc/fstab,追加或修改一行 # tmpfs /dev/shm tmpfs defaults,size=16G 0 0
第三层约束是Oracle版本本身的位数限制。32位Oracle实例的进程地址空间有限,即使操作系统内存充足,SGA也无法设置得很大;64位版本则基本不存在这个问题,理论上限取决于操作系统和硬件资源。此外,在Exadata或云环境(如OCI、AWS RDS)中,平台方可能对内存参数有额外限制或推荐值,部署前应查阅对应平台的最佳实践文档。
三、参数查看与修改方法
查看当前配置最直接的方式是查询v$parameter视图,同时可以结合show parameter命令。下面的查询会列出AMM相关的所有关键参数:
SELECT name, value, isdefault, issys_modifiable
FROM v$parameter
WHERE name IN ('memory_max_target','memory_target',
'sga_max_size','sga_target',
'pga_aggregate_target','pga_aggregate_limit')
ORDER BY name;修改MEMORY_TARGET属于在线操作,示例如下。假设当前MEMORY_MAX_TARGET为8G,可以将运行中的目标值从4G调整到6G:
-- 动态调整 MEMORY_TARGET(不能超过 MEMORY_MAX_TARGET) ALTER SYSTEM SET memory_target = 6G SCOPE = BOTH; -- 提高天花板需要写入 spfile 并重启实例 ALTER SYSTEM SET memory_max_target = 12G SCOPE = SPFILE; SHUTDOWN IMMEDIATE; STARTUP;
如果实例使用的是pfile启动,则需要直接修改init参数文件中对应的行,然后重启实例。这里有个实用技巧:在规划期就把MEMORY_MAX_TARGET设得比预期值高一些,比如物理内存的70%,而把MEMORY_TARGET设在相对保守的位置,比如物理内存的40%到50%。这样后续扩容内存时只需在线调整MEMORY_TARGET,避免了停机窗口的依赖。
四、AMM与ASMM的选择及常见问题
AMM虽然省心,但并不适合所有场景。一个广为人知的问题是,启用AMM后SGA使用的是/dev/shm中的共享内存文件,大页(HugePages)在这种模式下无法生效,这在物理内存达到数百GB的大型主机上会造成页表开销过大、TLB命中率下降的问题。因此对于大型核心系统,很多DBA会选择禁用AMM,将MEMORY_TARGET设为0,改用ASMM(设置SGA_TARGET和PGA_AGGREGATE_TARGET)并配合HugePages使用,性能收益往往更明显。
另一个常见问题是内存不足时的报错定位。如果/dev/shm设置过小,启动报ORA-00845;如果SGA内部空闲块碎片化严重,会报ORA-4031 unable to allocate memory;如果MEMORY_TARGET设得过小导致PGA分配受限,大量排序或哈希操作的会话可能出现性能急剧下降。排查思路是先看v$memory_target_advice视图,它会给出不同MEMORY_TARGET取值下的预估DB Time收益,是判断当前参数是否合理的第一手依据:
SELECT memory_size, memory_size_factor,
estd_db_time, estd_db_time_factor
FROM v$memory_target_advice;-- 内存粒度大小与时间估算当estd_db_time_factor在更小的memory_size下已经接近1.0时,说明当前配置已经够用,没必要继续加大内存;反之如果缩小内存后该因子明显上升,则说明内存确实是瓶颈,有加大的空间。同时也可以借助v$pgastat和v$sgastat分别观察PGA和SGA的实际使用峰值,确认自动分配是否合理。
总结来看,MEMORY_MAX_TARGET的合理上限没有一个放之四海而皆准的数字,核心原则是:不超过/dev/shm的大小,不超过物理内存扣除系统开销后的70%到80%,并预留出后续在线扩容的余量。小型和中型数据库使用AMM可以显著降低管理成本,而超大规模系统则建议评估HugePages加ASMM的组合方案。上线前做好容量规划,运行中定期参考内存建议视图,才是让这套机制稳定发挥价值的正确姿势。
MEMORY_MAX_TARGETOracle内存管理AMM自动内存管理修改时间:2026-09-06 06:02:34