前言
除了 SGA (System Global Area),Oracle 進程還使用三大進程私有記憶體區域:PGA (Program/Process Global Area)、UGA (User Global Area)、CGA (Call Global Area)。理解三者關係、內容組成、記憶體位置 (專用/共用伺服器模式)、動態分配與釋放機制,是診斷 ORA-4030、優化排序/雜湊、配置大頁面記憶體的核心基礎。
一、三大區域關係圖譜
進程
├── PGA (進程級,私有)
│ ├── Fixed PGA (原子變數、指標)
│ └── Variable PGA (PGA Heap)
│ ├── UGA (會話級,專用伺服器模式下為 PGA 子堆)
│ │ ├── Fixed UGA (~70 原子變數)
│ │ └── Variable UGA (UGA Heap)
│ │ ├── Open Cursors 持久區
│ │ ├── Package State/Variables
│ │ ├── Java Session State
│ │ ├── Enabled Roles
│ │ ├── Trace Events
│ │ ├── NLS Parameters
│ │ ├── Open DB Links
│ │ └── Session Access Control
│ └── CGA (呼叫級,PGA 子堆)
│ ├── SQL Parse/Execute/Fetch 狀態
│ ├── Recursive Call 緩衝
│ ├── Direct I/O Buffers
│ └── Java Call Memory (New/Old/Stack Space)
└── (共用伺服器模式:UGA 在 Shared Pool,PGA 僅含進程狀態)
二、PGA (Program/Process Global Area)
特性
- 進程私有記憶體,非共享記憶體
- 每個 Oracle 伺服器進程擁有獨立 PGA
- 無需 Latch 保護 (其他進程無法存取)
- 進程終止時自動釋放,資源清理機制天然可靠
組成
| 區域 | 內容 |
| Fixed PGA | 原子變數、小資料結構、指向 Variable PGA 的指標 |
| Variable PGA (PGA Heap) | 動態堆,Chunks 可查 X$KSMPP (結構同 X$KSMSP) |
PGA Heap 永久分配依賴參數
DB_FILES
LOG_FILES
CONTROL_FILES
三、UGA (User Global Area)
內容
- 開啟游標的持久運行時區域
- 套件狀態、變數
- Java 會話狀態
- 啟用的 Roles
- 啟用的 Trace Events
- 生效的 NLS 參數
- 開啟的 DB Links
- 會話存取控制
組成
| 區域 | 內容 |
| Fixed UGA | ~70 原子變數、小結構、指向 UGA Heap 指標 |
| UGA Heap | Chunks 可查 X$KSMUP (結構同 X$KSMSP) |
UGA Heap 永久分配依賴參數
OPEN_CURSORS
OPEN_LINKS
MAX_ENABLED_ROLES
記憶體位置:專用 vs 共用伺服器
| 模式 | UGA 位置 | Fixed UGA | UGA Heap |
| 專用伺服器 (Dedicated) | PGA 內 | PGA 中一個 Chunk | PGA 子堆 |
| 共用伺服器 (MTS/Shared Server) | SGA Shared Pool 內 | Shared Pool 中一個 Chunk | Shared Pool 子堆 |
四、CGA (Call Global Area)
特性
- 短暫存在:僅在資料庫呼叫期間 (Parse/Execute/Fetch)
- 遞歸呼叫需要獨立 CGA
- 無論 UGA 在 PGA 或 Shared Pool,CGA 總是 PGA 子堆
- 推論:呼叫期間會話必須綁定進程 → MTS 環境需足夠進程數應對並發呼叫
內容
- 遞歸呼叫資訊 (資料字典查詢、最佳化、觸發器執行)
- Direct I/O Buffers
- 其他臨時資料結構 (呼叫結束即釋放)
UGA 必須持久化的結構 (不在 CGA)
- SQL Area
- PL/SQL Area
- Sort Area
Java Call Memory (CGA 內特殊區域)
- 三代空間:Stack Space、New Space、Old Space
- New Space 多次 GC 存活 → 晋升 Old Space
- Oracle 記憶體管理中唯一的「垃圾回收」機制
五、進程記憶體動態分配
增長機制
- SGA 啟動後固定,PGA 動態增長
- 透過
malloc() / sbrk() 系統呼叫擴展堆
- OS 新虛擬記憶體 → PGA Heap 新區 (Extent,通常數 KB)
- 若需求大,可分配數千個 Extent
OS 限制與 ORA-4030
- 單進程堆上限:Kernel 參數
MAXDSIZ (可每進程調整)
- 系統全域虛擬記憶體上限:與 Swap Space 相關
- 超過任一限制 → ORA-4030: out of process memory
- 多數情況因 Swap 不足,而非單進程限制
診斷工具
- OS 層:
swap -l, vmstat, prstat
- Oracle 內建:
maxmem 工具 (部分平台) 檢視單進程最大堆與首個觸發限制
解決策略
| 症狀 | 對策 |
| Swap 不足 + 大量換頁 | 減少進程數、降低單進程記憶體 (PGA_AGGREGATE_TARGET、SORT_AREA_SIZE) |
| Swap 不足 + 換頁少 | 增加 Swap Space |
六、進程記憶體釋放與收縮
監控視圖
| 統計名稱 | 含義 |
| session uga memory | 當前會話 UGA 大小 (含內部自由空間) |
| session uga memory max | 會話存活期最大 UGA |
| session pga memory | 當前會話 PGA 大小 (含內部自由空間) |
| session pga memory max | 會話存活期最大 PGA |
觸發收縮操作
- 磁碟排序合併階段
DBMS_SESSION.FREE_UNUSED_USER_MEMORY (僅 MTS 模式可用)
DBMS_SESSION.RESET_PACKAGE 釋放套件變數記憶體
- 指派新空陣列給陣列變數
釋放機制細節
- 僅完整的 Free Heap Extent 歸還父堆/進程堆
- 內部自由空間仍保留在 Subheap 中
- 大多數 OS:Oracle 不歸還虛擬記憶體給 OS,進程虛擬記憶體維持高水位 (HWM)
- 閒置頁面會被換出 Swap
OS 統計難讀原因
進程虛擬記憶體長期維持 HWM,不反映實際使用量。必須使用 Oracle 內部統計 (V$SESSTAT/V$PROCESS_MEMORY) 替代 OS 統計。
七、MTS 環境特殊考量
DBMS_SESSION.FREE_UNUSED_USER_MEMORY 僅 MTS 可用,釋放大型套件陣列記憶體回 Large Pool/Shared Pool
- 優先使用
RESET_PACKAGE 或指派空陣列
- 呼叫並發高時需增加
PROCESSES 參數 (因 CGA 綁定進程)
結語
PGA/UGA/CGA 三層記憶體架構精確對應進程/會話/呼叫三個生命週期,設計極具工程美感。關鍵洞見:
1. UGA 位置隨架構切換 (專用→PGA,共用→Shared Pool) 是 MTS 記憶體規劃核心
2. CGA 綁定進程 限制 MTS 並發度,需權衡 PROCESSES 參數
3. 記憶體不歸還 OS特性> 導致 OS 統計失真,必須依賴 V$ 視圖
4. Java Call Memory 唯一 GC 機制影響 JVM 內存模型理解
掌握此架構,配合 PGA_AGGREGATE_TARGET (9i+) 或 SORT_AREA_SIZE (8i) 自動管理,可構建穩定高效的記憶體運作環境。
- 上一篇文章: Oracle 透明閘道同時存取多個 SQL Server 實戰:配置、DB Link、雙引號陷阱全解析
- 下一篇文章: Oracle 被鎖定進程強制終極方案:從 SQL Kill 到 OS 層面 Loop Kill 完整流程
Copyright ©
程式碼之家 All Rights Reserved