為什麼要搞清 Process Memory?
除了 SGA(共享記憶體),每個 Oracle 進程/會話擁有私有記憶體區域。混淆 PGA/UGA/CGA 會導致:ORA-4030 排查無門、MTS/專用伺服器模式選型失誤、PL/SQL 記憶體洩漏難查。本文釐清三者定義、關係、分配與釋放機制。
核心定義速查表
| 區域 | 全稱 | 屬於 | 生命週期 | 核心內容 |
| PGA | Process Global Area | **進程** | 進程存活期 | OS 資源控制塊、堆疊、Session 狀態指標、Fixed/Variable PGA |
| UGA | User Global Area | **會話** | 會話存活期 | 游標狀態、Package 變數、NLS 參數、Roles、DB Links、Fixed/Variable UGA |
| CGA | Call Global Area | **單次呼叫** | 呼叫期間(Parse/Execute/Fetch) | 遞迴呼叫上下文、直接 I/O Buffer、暫時排序區、Java Call Memory |
PGA:進程私有堆,不共享、不受 Latch 保護
- 位於 **Process Private Memory**(非 Shared Memory)。
- 每個 Server Process(專用/共享)擁有一個 PGA。
- 結構:
- Fixed PGA:原子變數、小結構、指向 Variable PGA 的指標(類比 Fixed SGA)。
- Variable PGA (PGA Heap):動態堆,Chunks 可查
X$KSMPP。受 DB_FILES、LOG_FILES、CONTROL_FILES 參數影響永久佔用部分。
- 進程死亡時,OS 自動回收整個 PGA 區域,無需 Oracle 介入。
UGA:會話狀態容器,位置隨連接模式漂移
- 內容:開啟游標、Package 狀態/變數、Java Session State、啟用 Roles/Events、NLS 設定、DB Links、Entry Control。
- 結構:Fixed UGA(~70 原子變數)+ Variable UGA (UGA Heap),Chunks 見
X$KSMUP。受 OPEN_CURSORS、OPEN_LINKS、MAX_ENABLED_ROLES 影響。
- 關鍵差異:
| 連接模式 | UGA 物理位置 | 隸屬關係 |
| 專用伺服器 | **PGA 內部** | Fixed UGA = PGA Chunk;UGA Heap = PGA Subheap |
| 共享伺服器 (MTS) | **SGA Shared Pool 內** | Fixed UGA = Shared Pool Chunk;UGA Heap = Shared Pool Subheap |
CGA:呼叫級暫存區,PGA 的 Subheap
- 僅在 Parse/Execute/Fetch 三類「最低層級呼叫」存在。
- 遞迴呼叫(如 Parse 時查 Data Dictionary、執行 Trigger)需要獨立 CGA 隔離上下文。
- 無論 UGA 在 PGA 或 SGA,**CGA 永遠是 PGA 的 Subheap** → 推論:**一次呼叫期間,Session 必須綁定一個 Process**。這是 MTS 架構中
PROCESSES 參數需大於 SESSIONS 的根本原因。
- 內容:遞迴呼叫資訊、Direct I/O Buffer、臨時結構。**SQL Area、PL/SQL Area、Sort Area 屬於 UGA**(需跨 Call 存活),不在 CGA。
- Java Call Memory 也在 CGA,分 Stack/New/Old Space,採用分代式 GC(Oracle 記憶體管理中唯一 GC 點)。
Process Memory Allocation:PGA 如何長大
- SGA 啟動固定;PGA 透過
malloc()/sbrk() 動態擴展。
- OS 為 PGA Heap 分配新 Virtual Memory 區(通常數 KB),需求大時可達上千區。
- 雙重限制:
- 單進程 Heap 上限:Kernel 參數
MAXDSIZ(可 per-process 調整)。
- 系統全域 Virtual Memory 上限:受 Swap Space 限制。
- 超限即拋 ORA-4030: out of process memory**。多數因 Swap 不足,而非單進程參數。
- 診斷:OS 工具看 Swap 使用率;部分平台可用 Oracle
maxmem 工具查單進程 Heap 上限與首個觸發限制。
- 對策:Swap 暴增+換頁頻繁 → 減少進程數/降低 PGA 目標;Swap 充足但換頁少 → 擴大 Swap。
Process Memory Deallocation:為什麼 OS 看不見 PGA 縮小?
- Oracle Heap **易長難縮**。僅特定操作觸發釋放:磁盤排序 Merge、
DBMS_SESSION.FREE_UNUSED_USER_MEMORY(僅 MTS)。
- 統計視圖:
V$MYSTAT/V$SESSTAT:session uga memory、session pga memory(含內部自由空間)
session uga memory max、session pga memory max:生命週期高水位
- 釋放機制:只有**整個 Free Heap Extent** 歸還父堆/進程堆,**內部碎片保留在 Subheap**。
- 關鍵現象:多數 OS 下,Oracle **不歸還 Virtual Memory 給 OS**,進程 VSZ 長期維持 HWM。無用頁面會被 Swap Out,導致 OS 統計(RSS/VSZ)難以解讀 → **請以 Oracle 內部統計為準**。
DBMS_SESSION.RESET_PACKAGE 釋放 Package 變數陣列記憶體(優先於 FREE_UNUSED_USER_MEMORY)。
實戰排查清單
| 現象 | 檢查重點 | 對策 |
| ORA-4030 | Swap 使用率、單進程 PGA Max (V$SESSTAT)、PGA_AGGREGATE_TARGET | 增 Swap、調大 PGA_AGGREGATE_LIMIT、優化排序/Hash Join SQL |
| MTS 下 UGA 爆 Shared Pool | LARGE_POOL_SIZE、SESSIONS vs PROCESSES、OPEN_CURSORS 洩漏 | 啟用 Large Pool、修復游標關閉邏輯、調大 Shared Pool |
| PL/SQL Package 記憶體洩漏 | Package 變數大型 Collection、SESSION UGA MEMORY MAX 持續增長 | 用 DBMS_SESSION.RESET_PACKAGE、改用暫時表、拆分 Package |
結語
PGA/UGA/CGA 的邊界劃分,本質上是 **Process vs Session vs Call** 三個維度的正交分解。專用伺服器模式下三者疊加簡單;MTS 下 UGA 移入 SGA、CGA 仍在 PGA,形成跨記憶體區的引用關係。掌握分配/釋放機制,才能從容應對 ORA-4030、Shared Pool 碎片化、Package 記憶體洩漏等疑難雜症。**記住:OS 看到的進程記憶體是謊言,Oracle 內部統計才是真相。**
- 上一篇文章: Oracle 鎖定會話秒查:三條 SQL 定位阻塞源頭並精準釋放
- 下一篇文章: Oracle Rollback Segment 全生命週期管理:從概念到故障排查
Copyright ©
程式碼之家 All Rights Reserved