| 指標 | Session ~650 (正常) | Session 1000+ (故障) | 啟用 HugePages 後 (Session ~430) |
PageTables (/proc/meminfo) | 94~95 GB | **110+ GB** | **164 MB** |
| Used Memory (含 PageTables) | ~107 GB | ~107 GB + Swap 13 GB | ~正常範圍 |
| Swap Usage | ~13 GB | ~14 GB (持續增長) | ~0 |
根因分析
未啟用 HugePages 時,Oracle SGA 使用**標準 4KB 頁框**。每個 Session 連接到 SGA 都需要建立頁表項 (PTE) 映射虛擬地址到物理地址。
- 單 Session 頁表開銷 ≈
SGA_SIZE / 4KB * 8 bytes (64位系統 PTE 8 字節)
- SGA = 200GB → 頁數 = 52M → 單 Session 頁表 ≈ **400 MB**
- 1000 Sessions → **400 GB 頁表記憶體** (遠超物理記憶體) → 實際受限於 Kernel 記憶體管理,表現為 PageTables 爆增、Swap 暴增、系統卡頓、PMON 無法獲取 Latch、背景進程啟動超時 (ORA-00445)。
解決方案:啟用 HugePages (2MB/1GB 大頁)
1. 計算建議 HugePages 數量
# 以 SGA_MAX_SIZE 為基準
HugePages_Total = (SGA_MAX_SIZE_GB * 1024 * 1024) / Hugepagesize_KB + 閒置緩衝(約 1000)
# 例:SGA_MAX_SIZE=240GB, Hugepagesize=2MB
HugePages_Total = (240 * 1024) / 2 + 1000 = 123,880
2. 修改 /etc/sysctl.conf
vm.nr_hugepages = 123880
vm.hugetlb_shm_group = 54321 # oinstall group gid
執行 sysctl -p。
3. 確認生效
cat /proc/meminfo | grep -i huge
# HugePages_Total: 123880
# HugePages_Free: 123880 (資料庫未啟動時)
# Hugepagesize: 2048 kB
4. 重啟資料庫驗證
sqlplus / as sysdba
STARTUP;
-- 觀察 alert.log: "Using huge pages for buffer cache"
cat /proc/meminfo | grep -i huge
# HugePages_Free 明顯減少,PageTables 降至 MB 級
效果對比
| 維度 | 無 HugePages | 啟用 HugePages |
| PageTables 佔用 | 數十~百 GB (隨 Session 線性增長) | **< 200 MB** (固定開銷) |
| CPU 開銷 | 高 (TLB Miss、Page Walk 頻繁) | 低 (TLB 覆蓋範圍大 512 倍) |
| Swap 壓力 | 極大 (頁表本身可被 Swap Out) | 幾乎無 |
| 啟動時間 | 正常 | 略快 (大頁分配一次性完成) |
最佳實踐建議
- 生產環境強制啟用 HugePages:特別是 **SGA > 50GB** 或 **Session > 500** 的系統。
- 關閉 Transparent HugePages (THP):
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 加入 /etc/rc.local 永久生效
THP 會干擾 Oracle 明確管理的 HugePages,導致效能抖動。
- 監控指標納入告警:
# 告警閾值建議
PageTables > 10GB → Critical
HugePages_Free < 5% Total → Warning
- AMM (MEMORY_TARGET) 與 HugePages 不相容:若使用 AMM,無法使用 HugePages → **生產建議改用 ASMM (SGA_TARGET + PGA_AGGREGATE_TARGET) + HugePages**。
核心結論:HugePages 將頁表開銷從 **O(Sessions × SGA/4KB)** 降為 **O(SGA/2MB)**,是大記憶體、高併發 Oracle 部署的**必選項**,而非可選項。
- 上一篇文章: Oracle FOR UPDATE vs FOR UPDATE NOWAIT/WAIT n:鎖定行鎖行為差異與實戰選型
- 下一篇文章: Oracle 常見異常代碼速查表與處理策略 (ORA-00001/01400/01555/01652/03113/04031/07445/12514/12541/28001)
Copyright ©
程式碼之家 All Rights Reserved