将关键进程的oom_score_adj设为-1000可使其豁免被oom killer杀死,需root权限执行echo -1000 > /proc/pid/oom_score_adj,并固化到systemd服务(oomscoreadjust=-1000)或启动脚本;注意该值不继承子进程,且须配合vm.swappiness=1和vm.overcommit_memory=2降低整体oom风险。

怎么设置 oom_score_adj 让关键进程豁免被杀
核心业务进程(如 mysqld、redis-server、yasdb)被 OOM Killer 杀掉,根本原因不是“内存用得多”,而是它的 oom_score 分太高——而这个分数由 oom_score_adj 显式调控。把该值设为 -1000,内核就会跳过它,不参与打分。
操作必须在进程启动后执行,且需 root 权限:
echo -1000 > /proc/$(pgrep -f "mysqld")/oom_score_adj- 如果进程有多个线程(如 Java 应用),需对每个
tid单独写入,不能只写主进程 PID - 该设置重启即失效,必须固化到启动脚本或 systemd service 文件中(例如在
[Service]段加OOMScoreAdjust=-1000) - 注意:CentOS 7 及更早版本使用的是
oom_adj(范围 -16 ~ +15),-17才等效于新内核的-1000;确认内核版本用uname -r
为什么改了 oom_score_adj 还被杀了
常见误判是以为设了 -1000 就万事大吉,但实际仍被杀,往往因为以下几点:
- 进程启动时还没来得及设置
oom_score_adj,OOM 就已触发——尤其在内存压力陡增场景(如批量导入、缓存预热) - systemd 启动的服务若未声明
MemoryLimit=或MemoryMax=,cgroup v2 下可能被统一限制,导致内核绕过oom_score_adj直接按 cgroup 策略 kill - 某些容器运行时(如早期 runc)会重置
/proc/[pid]/oom_score_adj,需在容器内通过securityContext.oomScoreAdj(K8s)或--oom-score-adj(docker CLI)显式传递 - 检查是否真生效:
cat /proc/$(pgrep -f "mysqld")/oom_score_adj必须返回-1000,不是-999或其他值
vm.swappiness=1 和 vm.overcommit_memory=2 配合才管用
单靠调 oom_score_adj 是被动防御;要降低 OOM 触发概率,必须减少内核“走投无路”的机会。这两项参数是生产环境 MySQL/Redis 类服务的标准组合:
-
vm.swappiness=1:让内核极度倾向回收 page cache,而不是换出匿名页(即尽量避免 swap)。swap in/out 延迟高,且一旦开始频繁 swap,OOM 往往紧随其后 -
vm.overcommit_memory=2:启用严格内存分配策略,禁止 overcommit。此时最大可分配内存 = 物理内存 ×vm.overcommit_ratio/100 + swap 大小。默认overcommit_ratio=50,即最多只允许分配一半物理内存的匿名页(比如 64G 内存 → 最多 32G + swap)。这能防止某个进程 malloc 出远超实际可用量的虚拟内存,后续一写就崩 - 二者必须一起用:只设
swappiness=1不防 overcommit;只设overcommit_memory=2不控 swap,仍可能因 swap 延迟引发级联延迟和 OOM
别信“关闭 OOM Killer”这种操作
网上常有建议写 vm.oom_kill = 0 或 vm.panic_on_oom=1 来“禁用 OOM”,这是危险误导:
-
vm.oom_kill = 0并非标准内核参数,多数发行版不识别,设了也无效 -
vm.panic_on_oom=1是让系统直接 panic 重启,比杀一个进程后果更严重——数据库正在刷盘时 panic,大概率损坏数据文件 - 真正可控、安全、可验证的方式只有两个:
oom_score_adj豁免关键进程 +overcommit_memory=2+swappiness=1降低整体内存风险面 - OOM Killer 本身不是 bug,是内核最后一道保命机制;目标不是消灭它,而是让它永远别瞄上你的核心进程
最易被忽略的一点:oom_score_adj 的值在进程 fork 子进程时不会继承,子进程会回到默认值 0。如果你的服务依赖子进程处理请求(如 Nginx worker、PHP-FPM child),必须对每个子进程单独设置,或改用 systemd 的 OOMScoreAdjust 全局配置。











