PGA内存不足典型现象是ORA-04030报错及sorts/hash joins(disk)飙升;确认方法包括查ASH定位高内存SQL、分析AWR中workarea执行模式分布,并验证workarea_size_policy=AUTO且无手动内存参数干扰。
PGA内存不足的典型现象和确认方法
oracle实例出现 ora-04030(out of process memory)或大量 sorts (disk)、hash joins (disk) 统计值飙升,基本可以锁定是pga不足。但别急着调大 pga_aggregate_target——先看awr里真实发生了什么。关键不是“缺多少”,而是“谁在吃”。运行以下查询定位高消耗sql:
SELECT sql_id,
ROUND(SUM(pga_memory_used)/1024/1024, 1) AS pga_mb,
COUNT(*) AS execs
FROM dba_hist_active_sess_history a
JOIN dba_hist_sqlstat s USING (sql_id)
WHERE sample_time > SYSDATE - 1
AND session_state = 'ON CPU'
GROUP BY sql_id
ORDER BY pga_mb DESC
FETCH FIRST 10 ROWS ONLY;
注意:这个结果依赖 DBA_HIST_ACTIVE_SESS_HISTORY 的采样完整性,如果没开ASH或保留时间太短,会漏掉短时大内存操作。
用AWR报告看workarea执行模式分布
打开最近一次AWR报告(awrrpt.sql),翻到「SQL Statistics → Memory Statistics」部分,重点关注三列:
-
Workarea executions – optimal:完全在内存完成,理想状态 -
Workarea executions – one-pass:单次落盘,性能明显下降 -
Workarea executions – multipass:多次读写临时表空间,严重瓶颈
如果 one-pass 占比超过 5%,说明部分操作已开始受压;若 multipass 非零,必须干预。这不是配置问题,是SQL本身或数据分布导致的workarea预估失准。
调整前先检查workarea自动管理是否真生效
pga_aggregate_target 不是“最大可用PGA”,而是Oracle用来估算每个workarea大小的基数。它生效的前提是:
-
workarea_size_policy必须为AUTO(默认,但可能被显式改过) - 相关SQL没有加
/+ OPT_PARAM('_smm_max_size' 'xxx') /这类hint覆盖 - 没有在session级执行过
ALTER SESSION SET sort_area_size = ...
查当前设置:
SHOW PARAMETER workarea_size_policy SHOW PARAMETER pga_aggregate_target
如果看到 sort_area_size 或 hash_area_size 非零,说明手动模式残留,自动管理被绕过。
调参时避开两个常见误操作
- 直接把
pga_aggregate_target 翻倍:PGA不是越大越好,它会挤占SGA,尤其在OLTP系统中可能引发buffer cache争用,反而降低吞吐
- 忽略并发度:一个SQL申请的workarea上限是
pga_aggregate_target / _smm_px_max_size(隐含参数,默认约20),但实际分配还受当前活跃会话数影响。100个并发排序,每个分到的内存可能只有理论值的1/10
pga_aggregate_target 翻倍:PGA不是越大越好,它会挤占SGA,尤其在OLTP系统中可能引发buffer cache争用,反而降低吞吐 pga_aggregate_target / _smm_px_max_size(隐含参数,默认约20),但实际分配还受当前活跃会话数影响。100个并发排序,每个分到的内存可能只有理论值的1/10 更稳妥的做法是:
- 先用
DBMS_SQLTUNE.REPORT_SQL_MONITOR抓单条问题SQL的实时执行计划,看哪个step的Temp Space或Memory Usage异常高 - 对该SQL加
/+ USE_HASH(table) /或重写谓词减少中间结果集,比调PGA更治本
真正难处理的是那些无法改写、又必须跑的报表SQL——这时候才考虑局部调大 _smm_max_size,而不是全局拉高 pga_aggregate_target。











