Linux OOM 機制

Yann發表於2019-09-18

之前專案組在一臺1核1G開發伺服器上協作開發, 伺服器上有 Nginx,PHP,Mysql 其他沒有耗資源的程式, 隨著測試資料上升及開發人員增加(mysql視覺化工具長連線也會耗記憶體) 導致mysql程式經常掛掉, 當時也想到是Mysql太佔資源, 但還是沒解釋通為什麼每次掛的都是mysql程式, 直到最近了解了Linux OOM機制。

Linux OOM機制

OOM killer(Out-Of-Memory killer): 該機制會監控那些佔用記憶體過大,尤其是瞬間很快消耗大量記憶體的程式,為了防止記憶體耗盡核心會把該程式殺掉。

說明:

  1. Linux核心根據應用程式的要求分配記憶體,通常來說應用程式分配了記憶體但是並沒有實際全部使用
  2. 為了提高效能,這部分沒用的記憶體可以留作它用,這部分記憶體是屬於每個程式的,核心直接回收利用的話比較麻煩,所以核心採用一種過度分配記憶體(over-commit memory)的辦法來間接利用這部分“空閒”的記憶體,提高整體記憶體的使用效率。

如果這些分配出去的記憶體需求超過實體記憶體(包括swap)的容量, 核心(OOM killer) 必須殺掉一些程式才能保障系統正常執行

檢測機制:

核心原始碼: linux/mm/oom_kill.c

  1. 系統記憶體不足時, out_of_memory() 被觸發
  2. 呼叫 select_bad_process() 選擇一個 “bad” 程式殺掉
  3. 如何判斷和選擇 “bad” 程式由 oom_badness()決定 <理論上最bad的程式是最佔用實體記憶體消耗量的程式>

oom_badness() 如何選擇 哪個程式是 “bad” 程式?

oom_badness() 給每個程式打分, 根據 points 的高低來決定殺哪個程式 (分數越低越不容易被殺掉, points 可以由adj來調節)
打分機制如下:

  • root程式有3%的記憶體使用特權,因此這裡要減去那些記憶體使用量
  • /proc/PID/oom_score_adj 影響打分 有效值是 -1000到1000之間的整數<-1000 禁止使用 oom killer -500:表示 分數對半折>
  • /proc/PID/oom_adj 已廢棄留作相容, kernel 會換算成oom_score_adj

PS: php-fpm程式 score 正常才 3 分 左右 , Mysql 程式 score 在300左右。。。

相關文章