Oracle从11g开始引入了自动内存管理(AMM,Automatic Memory Management),只需要设置memory_target和memory_max_target两个参数,数据库实例就会根据负载自动在SGA和PGA之间调配内存。而在AMM出现之前,DBA普遍使用的是ASMM(自动共享内存管理)加pga_aggregate_target的组合,甚至更早期的完全手工配置。三种方式各有适用场景,选错了不仅浪费内存资源,还可能引发性能问题。本文从原理、配置和风险三个角度对它们进行系统对比。

一、AMM的工作原理与参数配置
AMM的核心思想是把SGA和PGA的内存分配权整体交给Oracle。DBA只需告诉数据库实例总共能用多少内存,剩余的内部调配工作由数据库自动完成。启用AMM只需要两个参数:memory_target表示当前的目标内存总量,memory_max_target表示允许的上限。两者的关系类似于sga_target与sga_max_size的关系。
典型的配置方式如下,在spfile环境下执行后重启实例生效:
-- 设置AMM,总内存2G,上限4G ALTER SYSTEM SET memory_max_target = 4G SCOPE = SPFILE; ALTER SYSTEM SET memory_target = 2G SCOPE = SPFILE; -- 若之前配置过sga_target和pga_aggregate_target,建议置零 ALTER SYSTEM SET sga_target = 0; ALTER SYSTEM SET pga_aggregate_target = 0;
AMM有一个容易被忽视的前提条件:它依赖Linux的共享内存文件系统/dev/shm。Oracle在AMM模式下不再使用传统的POSIX共享内存段,而是通过在/dev/shm下创建内存映射文件来管理SGA。因此/dev/shm的大小必须大于或等于memory_max_target的值,否则实例启动时会直接报ORA-00845错误。这一点在Docker容器、某些云主机默认配置中特别容易踩坑,因为这些环境里/dev/shm默认往往只有64M。
可以通过下面的命令检查并调整/dev/shm大小:
# 查看当前/dev/shm大小 df -h /dev/shm # 临时重新挂载为4G mount -o remount,size=4G /dev/shm
从管理角度看,AMM的优势非常明显:DBA不需要理解各个内存组件的细节,数据库会根据工作负载动态地把内存从PGA挪到SGA,或者反过来。比如白天以查询为主时SGA自动扩大以容纳更多缓冲区,晚上批量排序任务增多时PGA部分自动增长,无需人工干预。
二、手动内存管理与ASMM的配置方式
在AMM出现之前,主流做法是ASMM加自动PGA管理。这种方式下,DBA需要分别设置sga_target和pga_aggregate_target,SGA内部的各组件(如db_cache_size、shared_pool_size、large_pool等)由Oracle自动调整,但SGA与PGA之间的边界是固定的,不会自动流动。更早的全手工模式则要求DBA逐个设置共享池、缓冲区缓存等参数,工作量极大且强烈依赖经验。
ASMM模式的典型配置如下:
-- SGA总大小3G,PGA目标1G ALTER SYSTEM SET sga_max_size = 3G SCOPE = SPFILE; ALTER SYSTEM SET sga_target = 3G; ALTER SYSTEM SET pga_aggregate_target = 1G;
ASMM使用传统的共享内存段(通过ipcs -a可以看到明显的shm段),不依赖/dev/shm,因此在某些受限环境下兼容性更好。它的代价是失去了SGA与PGA之间的自动调剂能力:如果白天OLTP负载重、夜间批量任务重,DBA可能需要通过定时任务在不同时段修改参数来适配负载,管理成本明显上升。
还有一类场景是必须使用手工模式的,比如使用了Oracle的巨大页(HugePages)优化。HugePages要求SGA使用传统共享内存段并锁定在物理内存中,而AMM与HugePages是互斥的。对于SGA达到几十甚至上百GB的大型数据库,使用HugePages可以显著减少页表开销、防止SGA被换出到swap,此时手工或ASMM加HugePages的组合才是正确选择。
三、如何查询当前内存管理方式与切换建议
判断数据库当前处于哪种内存管理模式,可以查看相关参数的取值。如果memory_target大于0,说明启用了AMM;如果memory_target为0而sga_target大于0,则是ASMM;两者都为0则是完全手工模式。同时,视图v$memory_dynamic_components和v$sga_dynamic_components能够观察内存组件的实际分配和resize历史,是排查自动调整是否合理的重要依据。
-- 查看当前内存参数
SELECT name, value FROM v$parameter
WHERE name IN ('memory_target','memory_max_target',
'sga_target','sga_max_size','pga_aggregate_target');
-- 查看各内存组件当前大小
SELECT component, current_size/1024/1024 AS size_mb
FROM v$memory_dynamic_components
ORDER BY current_size DESC;
在实际选型上,可以给出以下建议:中小型数据库、内存总量在几十GB以内、运维人力有限的场景,AMM是省心的选择,配置简单且大部分时间表现良好;大型核心数据库、SGA超过32G、计划使用HugePages或者Exadata等对内存布局有严格要求的平台,建议使用ASMM或手工模式,DBA对内存边界的控制更精确,也便于结合应用负载特征做针对性调优。
切换模式时要注意方向性:从AMM切换到ASMM,需要先把memory_target设为0,再设置sga_target和pga_aggregate_target,然后重启实例;反向切换则要先设置好memory_max_target再启用memory_target。无论哪个方向,都要预留足够的维护窗口,并提前确认/dev/shm的容量是否满足需求,避免切换过程中因ORA-00845导致实例无法启动。
最后补充一点,AMM虽然自动化程度高,但它内部基于统计信息的调度并非总是最优,个别系统会出现SGA被压缩导致缓存命中率下降的情况。因此即使启用了AMM,也应当定期通过AWR报告观察buffer cache命中率和PGA的溢出情况,必要时设置sga_target作为AMM模式下的下限保护,让自动管理与人工约束结合起来使用,这才是稳妥的运维思路。
Oracle AMM自动内存管理SGA与PGA修改时间:2026-09-07 15:34:47