一圖看懂三大記憶體區域隸屬關係
+------------------------- Oracle Instance -------------------------+
| SGA (Shared Memory) |
| +----------------+ +----------------+ +----------------+ |
| | Shared Pool | | Buffer Cache | | Redo Log Buffer| ... |
| +----------------+ +----------------+ +----------------+ |
| |
| Process Private Memory (per Server Process) |
| +-------------------------------------------------------------+ |
| | PGA (Process Global Area) | |
| | +------------+ +-----------------------------------------+ | |
| | | Fixed PGA | | Variable PGA (PGA Heap) | | |
| | | (Atomic, | | +-----------------------------------+ | | |
| | | Pointers) | | | UGA (if Dedicated Server) | | | |
| | +------------+ | | +------------+ +--------------+ | | | |
| | | | | Fixed UGA | | UGA Heap | | | | |
| | CGA | | +------------+ +--------------+ | | | |
| | (Call Global | | | CGA (Subheap of PGA) | | | |
| | Area) | | | - Recursive Call Context | | | |
| | - Subheap | | | - Direct I/O Buffer | | | |
| | of PGA | | | - Java Call Memory (Gen GC) | | | |
| +-------------------------------------------------------------+ |
+-----------------------------------------------------------------+
核心定義對照
| 區域 | 屬於 | 生命週期 | 物理位置 | 關鍵內容 |
| PGA | Process | Process 存活期 | Private Memory | OS 資源控制、Stack、Session 指標、Fixed/Variable PGA |
| UGA | Session | Session 存活期 | Dedicated: PGA 內 Shared (MTS): SGA Shared Pool | 游標狀態、Package 變數、NLS、Roles、DB Links |
| CGA | Call | 單次 Parse/Execute/Fetch | **永遠是 PGA Subheap** | 遞迴呼叫、Direct I/O Buffer、暫時排序、Java Call Memory |
UGA 位置隨連接模式漂移:關鍵架構差異
| 模式 | UGA 位置 | 隸屬 | 影響 |
| Dedicated Server | PGA 內部 | PGA Subheap | Session 1:1 Process,UGA 隨 Process 釋放 |
| Shared Server (MTS) | SGA Shared Pool | Shared Pool Subheap | Session > Process,**UGA 必須在 SGA 才能跨 Process 共享** |
推論:CGA 永遠是 PGA Subheap → **一次 Call 期間 Session 必須綁定一個 Process** → MTS 下 PROCESSES 需大於 SESSIONS。
PGA 動態擴展機制與 ORA-4030 根因
- 啟動時 PGA 極小,透過
malloc()/sbrk() 向 OS 申請 Virtual Memory 區(通常 4KB-64KB/區)。
- 需求大時可分配上千區,形成 PGA Heap 鏈表。
- 雙重限制:
- 單進程 Heap 上限:Kernel
MAXDSIZ(可 per-process 調整)。
- 系統全域 Virtual Memory 上限:受 **Swap Space** 限制。
- ORA-4030 多數因 Swap 不足**,而非單進程參數。
- 診斷:OS 工具看 Swap 使用率;部分平台用
maxmem 查單進程 Heap 上限與首個觸發限制。
記憶體釋放真相:為什麼 OS 看不見 PGA 縮小?
- Oracle Heap **易長難縮**。釋放觸發條件:磁盤排序 Merge、
DBMS_SESSION.FREE_UNUSED_USER_MEMORY(僅 MTS)、DBMS_SESSION.RESET_PACKAGE。
- 釋放粒度:**整個 Free Heap Extent** 歸還父堆,**內部碎片保留在 Subheap**。
- 多數 OS 下,Oracle **不歸還 Virtual Memory 給 OS**,進程 VSZ 長期維持 HWM(High Water Mark)。
- 無用頁面被 Swap Out,**OS 統計(RSS/VSZ)失真** → **請以 Oracle 內部統計為準**:
-- 當前 Session PGA/UGA 大小(含內部自由空間)
SELECT name, value FROM V$MYSTAT NATURAL JOIN V$STATNAME
WHERE name IN ('session pga memory','session uga memory',
'session pga memory max','session uga memory max');
Java Call Memory:CGA 內的分代 GC 孤例
- 位於 CGA,分 **Stack Space / New Space / Old Space** 三代。
- New Space 物件多次 Minor GC 存活 → 晉升 Old Space。
- **Oracle 記憶體管理中唯一採用分代 GC 的區域**;其他區域皆為「釋放 Dead Chunk」。
實戰排查速查表
| 現象 | 核心指標 | 對策 |
| ORA-4030 | Swap 使用率 > 80%、session pga memory max 巨大 | 增 Swap、調大 PGA_AGGREGATE_LIMIT、優化大排序/Hash Join SQL |
| MTS 下 Shared Pool ORA-4031 | UGA 佔用 Shared Pool 過大、LARGE_POOL_SIZE 不足 | 啟用 Large Pool、修復游標洩漏(OPEN_CURSORS)、調大 Shared Pool |
| PL/SQL Package 記憶體洩漏 | session uga memory max 隨時間單調增長 | 用 DBMS_SESSION.RESET_PACKAGE、拆分大 Collection、改用暫時表 |
| CGA 相關:遞迴呼叫過深 | SQL 解析時間長、recursive calls 巨大 | 簡化 SQL、用 Cursor Sharing、固定執行計畫 |
結語
PGA/UGA/CGA 的劃分本質是 **Process / Session / Call** 三維正交分解。Dedicated 模式下三者疊加;MTS 下 UGA 移入 SGA、CGA 留在 PGA,形成跨區引用。**記住三個鐵律**:
- CGA 永遠是 PGA Subheap → Call 期間 Session 綁定 Process。
- OS 看到的進程記憶體是謊言(HWM 不降),Oracle 內部統計才是真相。
- Java Call Memory 才有 GC,其他區域只釋放 Dead Chunk。
掌握分配/釋放機制,ORA-4030、Shared Pool 碎片、Package 洩漏皆可迎刃而解。
- 上一篇文章: Oracle 參數化視圖實戰:Package 變數法 vs 臨時表法,效能實測與結論
- 下一篇文章: Oracle 殭屍會話強制清除實戰:從 SQL KILL 到 OS orakill/kill -9
Copyright ©
程式碼之家 All Rights Reserved