初學 Oracle 時,常對 PGA(Program Global Area)與 UGA(User Global Area)的區別感到困惑。其實,這兩者的關係正如「進程」與「會話」的關係一般:雖然通常是一對一,但在共享服務器(MTS)架構下,會話數遠超進程數,二者的記憶體分配邏輯便截然不同。本文將從記憶體結構、組成區域、儲存位置等維度,深度剖析 PGA、UGA 及 CGA 的核心差異。
除系統全局區(SGA)外,Oracle 進程還使用三大全局記憶體區域:
PGA 位於進程私有記憶體中,不被其他進程共享。每個服務器進程擁有獨立的 PGA,包含該進程專屬的全局變量、數據結構及操作系統資源信息。因無併發訪問風險,PGA 結構無需 Latch 保護。
X$KSMPP 固定表查看 Chunk 詳情。其大小受 DB_FILES、LOG_FILES、CONTROL_FILES 等參數影響。PGA 記錄進程使用的 OS 資源與狀態信息。進程終止時,私有 PGA 可隨之自動清理釋放,避免資源洩漏。
UGA 承載會話級上下文,包括:
X$KSMUP 查看,受 OPEN_CURSORS、OPEN_LINKS、MAX_ENABLE_ROLES 參數影響。| 連接模式 | Fixed UGA 位置 | UGA Heap 位置 |
|---|---|---|
| 專用服務器 (Dedicated) | PGA 中的一個 Chunk | PGA 的子堆 |
| 共享服務器 (MTS) | Shared Pool 中的一個 Chunk | Shared Pool 的子堆 |
這也是 MTS 架構下「會話多於進程」的記憶體基石:UGA 必須放入 SGA 以便多進程共享訪問。
CGA 僅在 SQL 解析、執行、Fetch 等「調用」期間存在。遞歸調用(如解析時查數據字典、PL/SQL 執行 SQL、觸發器執行)均需獨立 CGA。
processes 參數。Java 調用內存同屬 CGA,但採用分代垃圾回收(Stack/New/Old Space),是 Oracle 內存管理中唯一的 GC 機制,其他區域均為釋放 Dead Chunk。
| 維度 | PGA | UGA | CGA |
|---|---|---|---|
| 作用域 | 進程 | 會話 | 單次調用 |
| 共享性 | 私有 | 視模式而定 (Dedicated 私有 / MTS 共享) | 私有 (屬於進程) |
| 生命週期 | 進程存活期 | 會話存活期 | 調用期間 |
| 核心內容 | OS 資源、進程狀態、排序/雜湊區 | 游標、包變量、會話上下文 | 遞歸調用、臨時 Buffer |
| 保護機制 | 無需 Latch | MTS 下需共享池鎖保護 | 無需 Latch |
理解 PGA/UGA/CGA 的分工,是掌握 Oracle 記憶體架構、排查 MTS 性能問題、優化 PGA 聚合目標(PGA_AGGREGATE_TARGET)的關鍵基石。