線上 4GB RDS 實例發生 OOM,MySQL 進程被 Kill。要破解此謎,必須先理解 Linux 內存分配的核心機制——OverCommit(過度提交)。本文從 malloc 行為差異、/proc/sys/vm/overcommit_memory 三種模式、用戶態驗證實驗三個維度,建立 Linux 內存分配心智模型。
malloc 失敗返回 NULL 表示物理內存+Swap 耗盡這是「樂觀分配」策略:假設應用申請後不會立即全量使用,提高內存利用率。
| 值 | 模式 | 行為 | 適用場景 |
|---|---|---|---|
| 0 | Heuristic(默認) | 內核啟發式算法:允許輕微過度提交,拒絕明顯超大請求;root 用戶額度更大 | 通用生產環境 |
| 1 | Always Overcommit | 無條件允許,只受虛擬地址空間限制(32位 4GB、64位 ~16TB) | 科學計算、稀疏矩陣、嵌入式無 Swap |
| 2 | Strict Overcommit | 禁止過度提交:CommitLimit = Swap + RAM × overcommit_ratio(默認 50%) | 嚴格合規、實時系統、無 Swap 環境 |
# 查看當前模式
cat /proc/sys/vm/overcommit_memory
# 查看 CommitLimit / Committed_AS
grep -i commit /proc/meminfo
1GB RAM + 400MB Swap 虛擬機
while (1) {
p = malloc(1MB);
if (!p) break;
printf("Allocated %d MB\n", ++count);
}
// 結果:申請到 ~1.4GB(RAM+Swap)甚至更多才失敗
while (1) {
p = malloc(1MB);
if (!p) break;
memset(p, 1, 1MB); // 觸發缺頁中斷,真正分配物理頁
printf("Allocated %d MB\n", ++count);
}
// 結果:申請到 ~1GB 左右(接近物理內存上限)即失敗或被 OOM Kill
當物理內存+Swap 即將耗盡,內核必須犧牲進程釋放內存。下一篇將深入 oom_badness() 評分算法、oom_score_adj 調控、MySQL 如何成為「首選犧牲者」及規避策略。