sga_max_size 管分配上限,它是实例启动时sga总内存的硬上限且不可动态增大;sga_target 是可在线调整的自动管理sga大小,必须≤sga_max_size,仅划定弹性调度池而非立即占用全部内存。
sga_max_size 和 sga_target 到底谁管分配上限?
sga_max_size 是 oracle 实例启动时能分配的 sga 总内存硬上限,一旦设了就不能动态调大(必须重启),而 sga_target 是当前实际可自动管理的 sga 大小,它必须 ≤ sga_max_size,且可以在线调整(只要不超上限)。
常见错误是把 SGA_TARGET 设得比 SGA_MAX_SIZE 还大,实例根本起不来,报错:ORA-00823: Specified value of sga_target is too large。也有人误以为调高 SGA_TARGET 就等于“立刻多占内存”,其实它只是划出一块可弹性调度的池子,各组件(如 shared_pool_size、db_cache_size)是否真用满,取决于负载和内部策略。
-
SGA_MAX_SIZE建议在初始化参数文件(spfile或pfile)中显式设置,避免 Oracle 自动推导出过小值(尤其在物理内存很大的机器上) - 若只设
SGA_TARGET没设SGA_MAX_SIZE,Oracle 会把它当作两者的初始值,但后续无法再扩大 SGA —— 因为SGA_MAX_SIZE被隐式锁定 - 启用自动内存管理(AMM)时,这两个参数会被禁用,改用
MEMORY_TARGET,混用会直接报错:ORA-00843: Parameter not valid for Automatic Memory Management
什么时候该手动固定子组件大小?
即使启用了自动 SGA 管理(即设置了 SGA_TARGET),Oracle 仍允许你对部分组件(如 shared_pool_size、db_cache_size)设下限值。这不是“建议”,而是必要干预点:当某类负载持续抖动(比如大量硬解析、LOB 频繁读写),自动调节可能跟不上节奏,导致反复收缩/扩张,反而引发 latch 竞争或缓存失效。
典型场景:OLTP 系统突然出现 library cache lock 等待,查 v$sgastat 发现 shared pool 频繁波动,这时可设 shared_pool_size = 1G(注意单位),Oracle 就不会再把它缩到 1G 以下 —— 但也不会超过这个值,哪怕 SGA_TARGET 还有余量。
- 设了下限后,该组件就变成“最小保障”,剩余 SGA 内存才由 Oracle 在其他可调组件间动态分配
-
large_pool_size、java_pool_size等非核心池子,设为 0 表示完全交由自动管理;设为非 0 则同样变成下限 - 别给
db_cache_size设过高下限(比如占掉SGA_TARGET的 90%),否则共享池、日志缓冲区等可能长期饥饿
怎么验证当前 SGA 分配是否生效?
别只看 show parameter sga,那只是参数值。真正要确认的是实例运行时的实际分配结果,尤其是 SGA_TARGET 是否被遵守、各组件有没有按预期浮动。
最直接的命令是:select * from v$sga; —— 看 value 列总和是否接近 SGA_TARGET;再查 v$sgastat,重点关注 free memory 行,如果长期低于 50MB,说明 SGA 紧张,可能需要调高 SGA_TARGET 或调整子组件下限。
- 重启后第一次查
v$sga,fixed size和variable size之和应 ≈SGA_MAX_SIZE,而非SGA_TARGET -
v$memory_dynamic_components只反映 AMM(内存目标模式)下的状态,SGA 模式下该视图里current_size全为 0,别误判 - 如果
SGA_TARGET调高了但v$sga总值没变,先确认是否用了alter system set sga_target=... scope=both,scope=memory不持久,实例重启就丢
Linux 上为什么 top 看不到 SGA 占用?
Oracle 在 Linux 下默认用 malloc + mlock 分配 SGA,内存被锁定(locked pages),不参与 swap,也不体现在单个进程的 RSS/VSS 里 —— 所以 top 或 ps 看不到 oracle 进程吃掉几个 GB。这是正常行为,不是配置失败。
要真实统计,得看 /proc/meminfo 里的 MemTotal 减去 MemFree 和 Cached 后的差值,再结合 v$sga 对齐;或者用 ipcs -m 查共享内存段(key 通常为 0x6b6d7367,对应 "kmsg" 字符串反转),bytes 列就是 SGA 实际占用。
- 若启用了
USE_LARGE_PAGES=only,SGA 会走大页(hugepages),此时更不会出现在进程 RSS 中,且必须提前在/proc/sys/vm/nr_hugepages配够页数,否则实例启动报ORA-27123 - 有些监控工具(如 Zabbix 默认模板)只抓
ps数据,会严重低估 Oracle 内存使用,需单独加v$sga或ipcs采集项 - SGA 占用的是物理内存,不是虚拟内存,所以
vmstat的si/so(swap in/out)为 0 不能说明内存充裕,得看free命令的available列
Oracle 的 SGA 配置不是设两个参数就完事,关键在理解“上限”“可用池”“子组件底线”三层控制关系,以及操作系统层面对内存可见性的差异。最容易被忽略的,是调参后不验证 v$sga 和 v$sgastat 的实时值,只信参数文件或监控图表。










