AWR默认不捕获短时高内存SQL,因其“SQL ordered by PGA Memory”仅统计执行≥1秒的SQL,而毫秒级大排序、PL/SQL集合赋值等漏网操作易触发ORA-04030;须结合ASH(session_state='ON CPU')补查,且需确认statistics_level=TYPICAL/ALL及ASH保留策略。

AWR默认不捕获短时高内存SQL
AWR的 SQL ordered by PGA Memory 列表只统计执行时间 ≥1 秒的 SQL,而真正吃 PGA 的操作(比如单次大排序、PL/SQL集合赋值、LOB构造)往往在毫秒级完成,根本进不了这个 Top N。你看到“PGA Memory used总量没爆”,但 ORA-04030 已经报了——大概率就是这类漏网之鱼干的。
实操建议:
- 必须补查
DBA_HIST_ACTIVE_SESS_HISTORY,用session_state = 'ON CPU'+pga_memory_used聚合,哪怕执行时间短,只要采样到 ON CPU 状态就会计入 - 如果查询结果为空,先检查
DBA_HIST_WR_CONTROL.retention是否小于 7 天,或确认 ASH 是否被禁用(SELECT value FROM v$parameter WHERE name = 'statistics_level'必须是TYPICAL或ALL) - 开发环境可临时开
10046trace 捕获可疑会话,但生产慎用——它本身也吃 PGA
v$pgastat 的 over allocation count 非零,但 AWR 里 workarea 分布看着正常
AWR 的 Memory Statistics 页只反映 workarea 类操作(排序/哈希/位图)的执行模式分布,但它完全不统计 PL/SQL 变量、游标缓存、LOB buffer、甚至某些解析器内部结构所占的 PGA。这些“非 workarea”内存暴涨时,Workarea executions – multipass 仍是 0,但 v$pgastat.over allocation count 已经 > 0,说明 Oracle 不得不反复调用 malloc() 扩堆——这是典型的“非典型 PGA 泄露”信号。
实操建议:
- 运行
SELECT name, value FROM v$pgastat WHERE name IN ('total PGA allocated', 'over allocation count', 'aggregate PGA auto target'),重点关注后两者是否持续增长 - 若
over allocation count在 1 小时内增长 > 10,且aggregate PGA auto target远低于total PGA allocated,基本可排除 SQL 问题,转向排查隐含参数或后台任务(如 MMON_SLAVE、Optimizer Statistics Advisor) - 检查是否启用了
_optimizer_adaptive_statistics或optimizer_adaptive_plans,它们在高并发解析场景下会偷偷吃掉数百 MB PGA
PGA_AGGREGATE_LIMIT 生效但 AWR 报告里找不到触发点
PGA_AGGREGATE_LIMIT 是硬限制,一旦突破直接报 ORA-04036 并 kill 进程,但它不记录“谁超的”,AWR 也不会为此生成快照。更麻烦的是:这个参数只在启用 MEMORY_TARGET 或显式未设 PGA_AGGREGATE_TARGET 时才真正生效;否则 Oracle 会退回到旧逻辑,AWR 里看到的全是“软目标”行为,根本对不上。
实操建议:
- 查
V$SPPARAMETER确认pga_aggregate_target是否为 0,再查memory_target是否非 0;二者必须满足其一,_pga_aggregate_limit才可能起作用 - 运行
SELECT name, value FROM v$pgastat WHERE name LIKE '%global%bound%',若返回空或远低于你设的_pga_aggregate_limit值,说明该参数实际未激活 - RAC 环境下必须逐节点检查,
ALTER SYSTEM SET "_pga_aggregate_limit"=... SCOPE=SPFILE SID='inst1'缺一不可
AWR 报告里 “PGA Memory MBytes” 曲线平滑,但系统频繁 OOM
AWR 的 PGA Memory MBytes 是每分钟一个采样点,而 Linux 的 oom_killer 或 Windows 的进程终止可能发生在任意毫秒级瞬间。当某条 SQL 在 200ms 内把 PGA 从 500MB 拉到 4GB,AWR 只会记下两个点:前一分钟 500MB,后一分钟 4GB——中间那道陡峭的悬崖,它看不见。
实操建议:
- 别只盯 AWR,立刻切到 OS 层:Linux 上用
grep -i "killed process" /var/log/messages定位被干掉的 Oracle 进程 PID,再反查ora_<pid>_<name>.trc</name></pid>里的PGA memory used快照 - 在数据库侧开启
PGA_AGGREGATE_LIMIT的拦截验证(用可控 PL/SQL 循环分配),确认它是否真在“挡事”,而不是形同虚设 - 如果发现
total PGA allocated峰值长期稳定在某个值附近(比如 3.2GB),但over allocation count却不断上涨,说明存在内存碎片——不是不够,是 Oracle 分配不到连续大块,这时调大参数反而恶化


















