ASH无法反映大对象内存等待,因其不采样PGA分配过程且不记录ORA-4030;真正信号是v$session_wait中的PGA memory operation等待事件及v$process_memory等实时指标。

ASH 无法直接反映大对象(如 BLOB、CLOB、PL/SQL 中的大型集合)分配引发的内存等待,因为它不采样 PGA 内存分配过程,也不记录 ORA-4030 或堆内存耗尽类错误;真正暴露该问题的是 v$session_wait 中的 PGA memory operation 等待事件,以及 v$process_memory 和 v$sesstat 的实时内存使用指标。
为什么 v$active_session_history 查不到大对象内存等待
ASH 每秒采样的是「活动会话状态」,而大对象分配(尤其是 DBMS_LOB.WRITE、PIPE ROW、COLLECT 大量行)通常表现为:
– 在 PGA 中快速申请/释放内存,不触发显式等待事件
– 即使发生 ORA-4030,错误发生在服务进程内部,ASH 中只显示 ON CPU 或极短的 library cache lock
– PGA memory operation 这个等待事件在 Oracle 19c+ 才正式支持,且默认不被 ASH 记录(需设置 _kghs_max_pga_wait_events=TRUE 才可能捕获)
– 所有与 UGA/PGA 分配相关的递归操作(如 kghalp 调用)均无 sql_id,ASH 里看到的常是 sql_id = '0000000000000000' 或空值
查 PGA memory operation 必须绕过 ASH 直接查 v$session_wait
该等待事件明确表示进程正在阻塞于内存分配路径(如 kghualloc),是诊断大对象内存瓶颈最直接信号。但不能依赖 ASH,必须实时轮询:
- 运行
SELECT sid, event, p1text, p1, p2text, p2, seconds_in_wait FROM v$session_wait WHERE event = 'PGA memory operation' AND seconds_in_wait > 0; - 配合
v$process查对应进程的pga_used_mem和pga_max_mem:若后者接近pga_aggregate_limit,说明已触顶 - 对疑似会话,立刻执行
SELECT name, value FROM v$sesstat s JOIN v$statname n ON s.statistic# = n.statistic# WHERE s.sid = &sid AND n.name IN ('session pga memory', 'session pga memory max'); - 注意:该事件在 RAC 中只出现在本地实例视图,
gv$session_wait可能延迟或漏报,优先查本实例
定位大对象来源:别只盯 SQL 文本,要看 v$open_cursor + v$session_longops
大对象操作往往隐藏在看似普通的语句背后(如 INSERT /*+ APPEND */ INTO t SELECT * FROM table(cast(... as my_nested_table_type)))。关键线索不在 ASH 的 sql_id,而在:
-
v$open_cursor中sql_text含LOB、CAST、PIPE ROW、COLLECT关键字,且child_number > 0(说明存在多版本,常因绑定变量类型不一致导致内存重分配) -
v$session_longops中opname为TABLE FETCH BY ROWID或LOB READ,且sofar增长缓慢但elapsed_seconds持续上升——表明 LOB 缓冲区反复翻页或内存拷贝卡顿 -
v$process_memory中heap_name = 'pga heap'且alloc_bytes > 100MB的进程,再关联v$session的program和module(如module = 'DataPump Worker'或program = 'ora_q000_...')
容易被忽略的两个硬限制:pga_aggregate_limit 和 _kghs_max_pga_wait_events
Oracle 12c+ 引入 pga_aggregate_limit 作为硬上限,一旦突破会强制终止会话并报 ORA-04030。但这个阈值默认基于物理内存动态计算,可能远低于 DBA 预期;而 _kghs_max_pga_wait_events 是隐藏参数,控制是否将 PGA 分配等待写入 v$session_wait(默认 FALSE):
- 确认当前限制:
SHOW PARAMETER pga_aggregate_limit;若为0,说明启用自动管理,需查v$pgastat的aggregate_pga_auto_target - 临时开启等待捕获(仅限诊断):
ALTER SYSTEM SET "_kghs_max_pga_wait_events" = TRUE SCOPE=BOTH;—— 重启后失效,且仅影响新连接 - 检查历史是否已超限:
SELECT * FROM v$pgastat WHERE name IN ('total PGA allocated', 'maximum PGA allocated');若后者接近前者,说明频繁触发收缩 - 注意:
_kghs_max_pga_wait_events不影响 ASH,它只增强v$session_wait,所以即使设了,v$active_session_history仍大概率为空
真正的大对象内存问题,从来不在 ASH 里“等出来”,而在 v$session_wait 里“堵出来”、在 v$process_memory 里“涨出来”、在 v$open_cursor 里“藏出来”。别花时间写 ASH 查询,先跑三行 v$ 视图,再看 pga_aggregate_limit 是否被悄悄压垮。


















