Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

深入解析 Linux OOM Killer 機制:原理、調優與最佳實踐

編輯:Linux 教學

前言:為什麼 MySQL 會「無緣無故」被殺?

作為 VPS 服務商,我們經常遇到客戶投訴:MySQL 進程莫名其妙消失,或者 VPS 頻繁死機。登入終端檢查日誌(/var/log/messages),總能看到熟悉的 Out of memory: Kill process 字樣。這正是 Linux 核心的 OOM Killer(Out-of-Memory Killer) 在作祟——當系統記憶體耗盡時,它會強制終止某個進程以釋放記憶體,防止整個系統崩潰。

核心為什麼會過度分配記憶體?

Linux 採用 Over-commit Memory(過度提交記憶體) 機制:應用程式申請記憶體時,核心往往直接答應,哪怕物理記憶體不夠。因為很多程式申請了記憶體卻從不完全使用,這樣能提高整體記憶體利用率。這就像銀行存貸款業務——平時只有一小部分人取錢,銀行運作正常;但若全體存戶同時提取所有存款,銀行就會破產。同理,當大多數程式同時耗盡各自的記憶體配額,總需求超過物理記憶體+Swap 時,OOM Killer 必須介入「犧牲」部分進程。

OOM Killer 如何選擇「犧牲品」?

核心原始碼 linux/mm/oom_kill.c 揭示了選擇邏輯:

  1. out_of_memory() 被觸發
  2. 呼叫 select_bad_process() 選擇「壞進程」
  3. 核心評分函式 oom_badness() 計算每個進程的「壞分」

演算法核心極其樸素:佔用記憶體越多,分數越高,越容易被殺。具體計算包含:

  • 進程的 RSS(常駐集合大小)
  • 頁表佔用
  • Swap 佔用
  • Root 權限進程享有 3% 加分優惠(分數降低)
  • 可透過 oom_score_adj 人工調整(-1000 到 1000,越小越安全)

這就是為什麼 MySQL 這類大記憶體佔用者總是「躺著也中槍」——它的體積通常最大,得分最高。

實戰解決方案:從源頭治理到應急調優

1. 根治之道:增加記憶體或優化應用

  • 升級實體記憶體(最直接)
  • 優化 MySQL 參數(innodb_buffer_pool_size、max_connections 等)
  • 精簡系統服務,騰出更多記憶體給核心應用

2. 核心參數調優:保護關鍵進程

透過 /proc/<PID>/oom_score_adj 降低關鍵進程分數:

# 找到 MySQL PID
ps aux | grep mysqld
# 將分數調低(-15 表示大幅降低被殺機率)
echo -15 > /proc/2196/oom_score_adj

驗證效果:

cat /proc/981/oom_score   # 原分 18
echo -15 > /proc/981/oom_score_adj
cat /proc/981/oom_score   # 新分 3,大幅降低風險

3. 極端情況:觸發 Kernel Panic 並自動重啟

sysctl -w vm.panic_on_oom=1
sysctl -w kernel.panic=10
echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=10" >> /etc/sysctl.conf

⚠️ 生產環境慎用,會導致系統重啟而非單一進程終止。

4. 徹底禁用 OOM Killer(不推薦生產環境)

sysctl -w vm.overcommit_memory=2
echo "vm.overcommit_memory=2" >> /etc/sysctl.conf

此模式下核心嚴格檢查記憶體申請,拒絕超額分配,但可能導致合理的記憶體申請失敗。

實用工具:快速定位高風險進程

以下 Bash 腳本列出系統中 oom_score 前 10 高的進程:

#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
    printf "%2d %5d %s\n" \
        "$(cat $proc/oom_score 2>/dev/null)" \
        "$(basename $proc)" \
        "$(cat $proc/cmdline 2>/dev/null | tr '\0' ' ' | head -c 50)"
done | sort -nr | head -n 10

輸出範例:

18  981 /usr/sbin/mysqld
4 31359 -bash
4 31056 -bash
1 31358 sshd: root@pts/6
...

總結

OOM Killer 是 Linux 記憶體管理的最後防線,而非錯誤。理解其評分機制,結合「擴容 → 優化 → 調優」三步走策略,才能從根本上避免核心服務被誤殺。生產環境建議:優先優化應用與系統記憶體佔用,輔以 oom_score_adj 保護核心進程,避免盲目禁用 OOM 機制。

Copyright © Windows教程網 All Rights Reserved