news 2026/9/26 3:48:39

Oracle内存全面分析(6):PGA内存结构与配置实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Oracle内存全面分析(6):PGA内存结构与配置实战

1. 从一次凌晨告警说起:PGA 到底吃掉了多少内存

很多 DBA 对 SGA 的调优已经形成肌肉记忆,但一碰到 PGA 就有点发怵。原因很简单:SGA 是启动时就分配好的共享内存,大小基本可控;而 PGA 是每个服务进程私有的内存区,随会话数、SQL 复杂度、排序和 Hash 操作动态涨落,稍不注意就会把物理内存吃穿。

我遇到过最典型的一次,是某套 OLTP 库在业务高峰期出现ORA-04030: out of process memory when trying to allocate,同时操作系统层面swap飙升。查下来不是 SGA 的问题,而是 PGA 在自动管理模式下被大量并发排序和 Hash Join 撑爆了。PGA(Program Global Area,程序全局区)是 Oracle 为每个服务进程创建的非共享内存区,一个进程对应一个 PGA,只有拥有它的进程才能读写,因此内部结构不需要 Latch 保护。它主要包含私有 SQL 区、游标与 SQL 区、会话内存,以及排序、Hash Join、Bitmap 操作使用的 SQL 工作区。

这篇是 Oracle 内存分析系列的第 6 篇,聚焦 PGA 的结构与配置实战。我会从 PGA 组成讲起,结合 OLTP 与批处理两类场景,给出可复制的参数配置骨架和验证 SQL,帮你快速定位 PGA 使用异常并完成调优验证。适合已经会看 AWR、想进一步把 PGA 管明白的 DBA 和运维同学。

2. 先把 PGA 的结构和自动管理机制理清楚

2.1 PGA 由哪几块组成

PGA 分为固定 PGA 和可变 PGA(PGA 堆)两部分。固定 PGA 大小固定,存放原子变量、小数据结构和指向可变区的指针;可变 PGA 是一个受管理的内存堆,主要包含三块内容:

私有 SQL 区保存绑定变量值和运行时内存结构,每个执行 SQL 的会话都有一份。它又分永久区(绑定变量信息,游标关闭时释放)和运行区(执行结束即释放,查询类要等所有行 fetch 完或查询取消才释放)。

游标与 SQL 区由用户进程管理,能分配多少私有 SQL 区受OPEN_CURSORS控制,默认 50。游标不关,永久区就一直占着内存。

会话内存保存登录信息等会话变量。专有服务器模式下它是私有的;共享服务器模式下它放在 SGA 里共享。

真正吃内存的大头是 SQL 工作区,服务于排序(ORDER BY、GROUP BY、ROLLUP、窗口函数)、Hash Join、Bitmap merge、Bitmap create 这几类操作。工作区越大,操作越快,但内存消耗也越高;工作区不够,数据就得到临时表空间落盘,响应时间明显拉长。

2.2 自动管理模式怎么工作

9i 之后引入PGA_AGGREGATE_TARGET,把所有*_AREA_SIZE参数统一接管。WORKAREA_SIZE_POLICY决定策略,默认AUTO,即由PGA_AGGREGATE_TARGET管理 PGA;设为MANUAL才回到手工调SORT_AREA_SIZE那一套。注意自动管理只管工作区,固定 PGA 那部分不受影响。

设置PGA_AGGREGATE_TARGET后,每个进程的 PGA 还受额外限制:串行操作时单进程可用 PGA 为MIN(PGA_AGGREGATE_TARGET * 5%, _pga_max_size/2),隐含参数_pga_max_size默认 200M;并行操作时并行语句可用 PGA 为PGA_AGGREGATE_TARGET * 30% / DOP。10g 之后,专有服务器和共享服务器模式下自动管理都生效。

2.3 专有服务与共享服务的差异

内存区专有服务共享服务
会话内存私有(PGA)共享(SGA)
永久区PGASGA
SELECT 运行区PGAPGA
DML/DDL 运行区PGAPGA

这张表很关键:共享服务器模式下,会话内存和永久区跑到了 SGA,所以 PGA 压力会小一些,但 SGA 要相应留足。判断 PGA 异常前,先确认实例用的是哪种服务模式。

3. 可复制的 PGA 参数配置骨架

3.1 先算目标值

Oracle 给过一个经验公式(Metalink Note 223730.1):OLTP 系统PGA_AGGREGATE_TARGET = (物理内存 * 80%) * 20%;DSS 系统PGA_AGGREGATE_TARGET = (物理内存 * 80%) * 50%。比如 8G 物理内存的 OLTP 库,推荐值约(8 * 80%) * 20% = 1.28G。

注意:这只是起点,不是终点。真实值要结合V$PGA_TARGET_ADVICE的建议和实际cache hit percentage来定。

3.2 配置骨架

下面这套配置适合大多数专有服务器模式的 OLTP 库,你可以按实际内存调整:

-- 查看当前设置 SHOW PARAMETER pga_aggregate_target; SHOW PARAMETER workarea_size_policy; -- 设置 PGA 自动管理(OLTP 场景,物理内存 8G) ALTER SYSTEM SET workarea_size_policy = AUTO SCOPE = BOTH; ALTER SYSTEM SET pga_aggregate_target = 1280M SCOPE = BOTH; -- 确认生效 SHOW PARAMETER pga_aggregate_target;

批处理/DSS 场景可以把目标值调大,并适当放开并行:

-- DSS 场景,物理内存 32G,目标值约 12G ALTER SYSTEM SET pga_aggregate_target = 12G SCOPE = BOTH; ALTER SYSTEM SET workarea_size_policy = AUTO SCOPE = BOTH; -- 并行相关,按需调整 SHOW PARAMETER parallel_degree_policy;

OPEN_CURSORS也建议一并检查,游标开太多会持续占用私有 SQL 区:

SHOW PARAMETER open_cursors; -- 应用确实需要大量游标时再调大,默认 50 对多数场景够用 ALTER SYSTEM SET open_cursors = 300 SCOPE = BOTH;

提示:_pga_max_size是隐含参数,默认 200M,不建议随意修改。它限制单进程 PGA 上限,改大了可能让单个进程吃掉过多内存。

4. 验证请求与成功结果:用视图把 PGA 看透

4.1 看整体使用情况

V$PGASTAT是 PGA 诊断的第一站,累加数据从实例启动开始统计:

SELECT name, value, units FROM v$pgastat ORDER BY name;

重点看几个指标:aggregate PGA target parameter是当前目标值;aggregate PGA auto target是自动模式下可用于工作区的内存,如果它相对目标值太小,说明大量 PGA 被 PL/SQL、Java 等组件占用;global memory bound是单个工作区可用上限,若降到 1M 以下就该考虑加大目标值;total PGA allocated是当前实际分配总量,短期超过目标值属正常;cache hit percentage若为 100%,说明所有工作区都拿到了最佳内存,低于 100% 说明有操作在落盘。

4.2 看建议器给出的目标值

V$PGA_TARGET_ADVICE会模拟不同目标值下的性能表现,前提是STATISTICS_LEVEL不是BASIC:

SELECT pga_target_for_estimate / 1024 / 1024 AS target_mb, pga_target_factor, estd_pga_cache_hit_percentage, estd_overalloc_count FROM v$pga_target_advice ORDER BY pga_target_for_estimate;

挑选estd_pga_cache_hit_percentage接近 100% 且estd_overalloc_count为 0 的最小目标值,就是性价比最高的配置。

4.3 定位具体是哪条 SQL 在吃内存

V$SQL_WORKAREA显示游标使用的工作区信息,可以 joinV$SQL找到语句:

SELECT s.sql_text, w.operation_type, w.policy, w.estimated_optimal_size / 1024 / 1024 AS est_optimal_mb, w.last_memory_used / 1024 / 1024 AS last_used_mb, w.last_execution, w.total_executions, w.optimal_executions, w.onepass_executions, w.multipasses_executions FROM v$sql_workarea w JOIN v$sql s ON s.hash_value = w.hash_value AND s.child_number = w.child_number WHERE w.policy = 'AUTO' ORDER BY w.last_memory_used DESC FETCH FIRST 20 ROWS ONLY;

last_execution为OPTIMAL说明内存够用;出现ONE PASS或MULTI-PASS就说明工作区不足,数据在落盘。multipasses_executions大于 0 的语句是重点优化对象。

4.4 看当前活动工作区

V$SQL_WORKAREA_ACTIVE提供瞬时信息,能抓到正在超额分配或落盘的工作区:

SELECT sid, operation_type, policy, work_area_size / 1024 / 1024 AS work_area_mb, expected_size / 1024 / 1024 AS expected_mb, actual_mem_used / 1024 / 1024 AS actual_mb, max_mem_used / 1024 / 1024 AS max_mem_mb, number_passes, tempseg_size / 1024 / 1024 AS tempseg_mb FROM v$sql_workarea_active ORDER BY actual_mem_used DESC;

当actual_mem_used明显大于expected_size,说明内存被超额分配;number_passes大于 0 说明发生了落盘。

4.5 看进程级 PGA 占用

V$PROCESS能直接看到每个进程的 PGA 使用:

SELECT spid, program, pga_used_mem / 1024 / 1024 AS used_mb, pga_allocated_mem / 1024 / 1024 AS alloc_mb, pga_max_mem / 1024 / 1024 AS max_mb FROM v$process ORDER BY pga_max_mem DESC FETCH FIRST 20 ROWS ONLY;

pga_max_mem排在前面的进程,就是历史上吃 PGA 最狠的,结合program能判断是哪个应用或后台进程。

4.6 看排序落盘比例

V$SYSSTAT里sorts (memory)和sorts (disk)的比值能快速判断排序是否健康:

SELECT name, value FROM v$sysstat WHERE name IN ('sorts (memory)', 'sorts (disk)', 'sorts (rows)');

sorts (disk)占比过高,说明排序区普遍不够,要么加大PGA_AGGREGATE_TARGET,要么优化 SQL 减少排序量。

5. 本篇常见错排查

5.1 ORA-04030 进程内存不足

报错ORA-04030: out of process memory when trying to allocate,通常是 PGA 总量或单进程上限被打满。排查顺序:先查V$PGASTAT的total PGA allocated是否远超目标值;再查V$SQL_WORKAREA_ACTIVE看是否有工作区在疯狂超额分配;最后查V$PROCESS定位具体进程。处理手段是适度加大PGA_AGGREGATE_TARGET,同时优化那些MULTI-PASS的 SQL。

5.2 cache hit percentage 长期偏低

如果V$PGASTAT里cache hit percentage长期低于 90%,说明大量工作区在落盘。先用V$PGA_TARGET_ADVICE确认加大目标值能否改善,再检查是不是有超大排序或 Hash Join 语句。有时候问题不在 PGA 大小,而在 SQL 本身写得让优化器选了糟糕的执行计划。

5.3 目标值设了但没生效

WORKAREA_SIZE_POLICY如果是MANUAL,PGA_AGGREGATE_TARGET就不起作用。用SHOW PARAMETER workarea_size_policy确认,必要时改成AUTO。另外 9i 在 OpenVMS 上不支持自动管理,10g 才支持,老环境要注意。

5.4 共享服务器模式下 PGA 视图对不上

共享服务器模式下,会话内存和永久区在 SGA,PGA 视图反映的只是工作区那部分。如果按专有服务器的经验去套,会误判 PGA 偏小。先确认服务模式,再解读视图。

5.5 并行查询把 PGA 吃爆

并行操作时可用 PGA 为PGA_AGGREGATE_TARGET * 30% / DOP,DOP 越高,单个并行语句能用的内存越少,反而更容易落盘。如果并行语句多,要么降低 DOP,要么加大目标值,别盲目开高并行。

6. 把 PGA 管明白,从看懂视图开始

PGA 调优的核心不是背参数,而是建立“看视图—找异常—调参数—再验证”的闭环。日常巡检我习惯先跑一遍V$PGASTAT看cache hit percentage和over allocation count,再用V$SQL_WORKAREA捞出MULTI-PASS的语句,最后用V$PGA_TARGET_ADVICE确认目标值是否合理。这套流程跑顺了,PGA 异常基本都能在告警之前发现。

如果你在验证模型或排查接入问题时需要快速对比不同模型的输出,可以到 TaoToken 模型对话 直接试;需要长期跑编码或 Agent 任务,Coding Plan 更合适;接入配置和密钥管理在 API Keys 和 接入文档 里都有现成示例,API 入口是https://taotoken.net/api。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 3:48:29

FastMCP MCP 服务全流程开发指南:用 TaoToken 统一 Key 打通配置与调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/26 3:48:13

无铬鞣皮板发硬怎么办?从鞣制化学到工艺调整全解析

直接进入正题。最近走访了几家做订单配套的皮厂,聊到一个普遍到不能再普遍的现象:客户要求改用无铬鞣,货做出来了,皮板却硬得像纸板,软度测试直接拉垮,浸水回软也救不回来,最后只能降价处理或者…

作者头像 李华
网站建设 2026/9/26 3:46:36

支付逻辑漏洞排查指南:8类常见漏洞与修复方案

做了这么多年支付风控和渗透测试,我最深的体会是:真正让企业一夜之间损失惨重的,往往不是SQL注入、不是RCE,而是那些看起来人畜无害,打起来刀刀见血的支付逻辑漏洞。它不依赖你用了什么框架、什么中间件,只…

作者头像 李华