首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL OOM 系列(二):OOM Killer 評分算法、oom_score_adj 與進程生存博弈

     編輯:MySQL 綜合教學

前言

內存兌付失敗時,Linux 由 oom_kill_process() 選擇犧牲者。選擇依據是 oom_badness() 計算的分數(/proc//oom_score),分數越高越先死。本文逐行解讀內核源碼邏輯,實驗驗證 oom_score_adj(-1000~1000)對生存率的決定性影響,為 MySQL 免殺奠基。

一、oom_badness() 核心邏輯(kernel/fork.c)

points = p->mm->total_vm;                    // 1. 基礎分 = 進程物理頁數(RSS,不含 Swap)
points += 子進程獨立 mm 的 total_vm;         // 2. 累加子進程物理內存
points /= sqrt(cpu_time);                    // 3. CPU 時間長 → 分數降低(保護長運行進程)
points /= sqrt(sqrt(run_time));              // 4. 存活時間長 → 分數降低(保護系統服務)
if (task_nice(p) > 0) points *= 2;           // 5. 低優先級 → 分數翻倍
if (capable(CAP_SYS_ADMIN) || uid==0) points /= 4; // 6. root/特權進程 → 分數降低
if (capable(CAP_SYS_RAWIO)) points /= 4;     // 7. 直接硬件訪問 → 分數降低
points <<= oom_score_adj;                    // 8. 用戶態調控:左移 oom_score_adj 位(-1000~1000)

關鍵洞察:

  • 基礎分與 RSS 正相關 → 內存大戶首當其衝
  • oom_score_adj 為 指數級影響:+1000 必殺、-1000 免死金牌
  • MySQL 典型特徵:大 RSS、長運行、root 權限、無 RAWIO → 基礎分高、保護因子有限

二、實驗驗證:oom_score_adj 生死線

環境

2GB RAM + 400MB Swap,啟動 3 個 1GB 申請+分級寫入進程

默認情況(adj=0)

第一個達到物理上限的進程被 Kill,oom_score=1000

設置 adj=15(最高風險)

echo 15 > /proc//oom_score_adj

該進程優先被 Kill,驗證指數級懲罰

設置 adj=-1000(免死金牌)

echo -1000 > /proc//oom_score_adj

進程存活,但系統可能因無可殺進程而崩潰(極端風險)

三、MySQL 為什麼容易被 Kill?

結論:MySQL 是教科書級的「高分候選者」。

四、禁用 OverCommit 可行嗎?

  • overcommit_memory=2:MySQL 啟動申請 Buffer Pool 即失敗(申請 > CommitLimit),或運行中動態擴展失敗 → Crash
  • 生產環境強烈不建議,會將「概率性 OOM Kill」轉為「確定性啟動失敗/運行時 Crash」

五、下一篇預告:MySQL 免殺三板斧

  1. 合理規劃內存佔用(Buffer Pool 上限、連接內存上限)
  2. 設置 oom_score_adj = -800(保留系統核心進程生存空間)
  3. 建立內存水位監控 + 自動熔斷(Kill 閒置連接、限流)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
因子MySQL 現狀影響
RSS 大Buffer Pool 佔物理內存 60-80%基礎分極高
長運行月級存活run_time 保護有限(四次方根)
root 權限通常 mysql 用戶非 root無 root 保護
子進程無 fork 子進程無額外累加
oom_score_adj默認 0無人為保護