pga内存不足时典型报错为ora-04030或ora-01652,应先查v$pgastat中allocated与used差值及v$sql_workarea_active中的onepass/multipass操作,再合理设置_pga_aggregate_target和pga_aggregate_limit,并确认是否启用amm。
pga内存不足时的典型报错和定位方法
oracle报ora-04030(无法分配内存)或ora-01652(临时段扩展失败),八成是pga撑不住了。别急着调大_pga_aggregate_target,先确认是不是真缺——查v$pgastat里total pga allocated和total pga used mem的差值是否长期接近零;再看v$sql_workarea_active里有没有大量onepass甚至multipass执行的sql,这类操作最吃pga。
- 用
SELECT * FROM V$PGASTAT WHERE name IN ('total PGA allocated', 'total PGA used mem', 'cache hit percentage');快速摸底 -
onepass表示数据量略超工作区,需一次磁盘交换;multipass意味着反复读写临时表空间,性能断崖式下跌 - 注意:
V$PGASTAT的统计是实例级汇总,不能定位到具体会话,得配合V$PROCESS和V$SESSION关联查
设置_PGA_AGGREGATE_TARGET的合理范围怎么定
这个参数不是越大越好。设太高,OS物理内存被Oracle PGA占满,触发系统级swap,反而让所有操作变慢;设太低,排序/哈希连接被迫落盘,SQL执行时间飙升。关键看实际负载类型:
- OLTP为主:建议设为物理内存的15%–25%,且单个会话平均PGA用量通常
10MB,总并发会话数×10MB可作下限参考 - DW/报表类:可能需要30%–50%,但必须同步检查
pga_aggregate_limit(12c+默认启用),它硬性限制PGA上限,避免失控,其默认值是_PGA_AGGREGATE_TARGET的2倍,可按需调整 - 混合负载:优先保障高峰时段的
V$SQL_WORKAREA_HISTOGRAM中optimal执行占比>95%,低于这个值就该调参
_PGA_AGGREGATE_TARGET和pga_aggregate_limit的关系与冲突
12c起Oracle加了pga_aggregate_limit作为安全阀,它比_PGA_AGGREGATE_TARGET更硬——哪怕目标设得再低,只要进程实际申请超过这个硬限,就会直接报ORA-04036(PGA内存超出限制)。很多人只调前者,忘了后者还在默默卡脖子。
-
pga_aggregate_limit默认 =MAX(2GB, 2 × _PGA_AGGREGATE_TARGET),但若系统内存<16GB,它会取2GB,此时即使你把_PGA_AGGREGATE_TARGET设到3GB也白搭 - 查当前值:
SHOW PARAMETER pga_aggregate_limit,修改需用ALTER SYSTEM SET pga_aggregate_limit = 8G SCOPE=BOTH; - 注意:该参数不支持动态降级(比如从8G降到4G),会报
ORA-02097,必须重启实例
自动内存管理(AMM)下_PGA_AGGREGATE_TARGET是否有效
无效。如果启用了MEMORY_TARGET(即AMM),Oracle会动态在SGA和PGA之间划拨内存,此时_PGA_AGGREGATE_TARGET只是个“建议值”,实际不受控。想精准管PGA,必须关AMM,改用ASMM(自动共享内存管理)。
- 检查是否启用AMM:
SHOW PARAMETER memory_target,非零即启用 - 切换到ASMM:需设
MEMORY_TARGET=0、SGA_TARGET>0、PGA_AGGREGATE_TARGET>0,然后重启实例 - ASMM下
PGA_AGGREGATE_TARGET才真正生效,且V$PGASTAT的统计更可信
Oracle的PGA调优不是填数字游戏,真正难的是在业务高峰期抓准那一两分钟的V$SQL_WORKAREA_ACTIVE快照,再比对pga_aggregate_limit是否悄悄成了瓶颈。多数人调完参数没验证onepass率,等于只拧了螺丝没测扭矩。











