OOM Killer:内存爆了,系统先杀谁
网站突然502、进程莫名其妙没了,查日志发现一行Out of memory: Killed process——这就是OOM Killer干的。小够讲清它的杀人逻辑、怎么查、怎么防。
我是小够。网站跑着跑着502了,SSH上去一看,进程没了,日志里躺着一行Out of memory: Killed process XXX。这不是黑客,是Linux内核的OOM Killer(内存不足杀手)在"断臂求生"。今天讲清它的逻辑,下次遇到不慌。
为什么需要Killer
内存耗尽时,系统有两个选择:整个死机,或者杀掉一些进程保住系统。Linux选了后者——宁可杀几个进程,也要让系统活着。这就是OOM Killer,内核的最后防线。
它按什么顺序杀人
内核给每个进程打了个"该杀分"(oom_score),分数越高越先死。打分逻辑大致是:占内存越多,分数越高。所以MySQL、Java应用这种内存大户,总是第一批上断头台;而sshd这种小进程,分数低,一般能活下来——这也是为什么进程死了你还能SSH上去看日志。
但有两个例外:
- oom_score_adj:可以手动调。把关键进程(比如数据库)调成-1000,Killer就永远不杀它。代价是内存真爆了,系统可能直接卡死——保护了一个,赌上全部,自己权衡。
- root进程有优待:内核对root跑的进程手下留情一点,但内存大户该杀还是杀,别指望。
怎么确认是它干的
dmesg | grep -i "killed process"
或者:
journalctl -k | grep -i "out of memory"
看到Killed process XXX (mysqld) total-vm:...,凶手就是它。很多"网站半夜502、早上自己好了"(其实是监控/定时任务重启了进程),根因都是OOM。
怎么防
按优先级排序:
- 加内存:根因永远是内存不够。1G跑WordPress+MySQL,爆是迟早的事,别挣扎。
- 限制应用内存:MySQL调小
innodb_buffer_pool_size,PHP调小memory_limit,Java设-Xmx。让每个进程知道自己几斤几两。 - 加Swap:上篇讲过,Swap是缓冲垫,能争取时间,但治不了本。
- 监控告警:内存用到80%就告警,别等爆了才知道。Uptime Kuma、Netdata都能做,5分钟配置。
- 保护关键进程:实在没钱加内存,给数据库设
oom_score_adj=-500,至少保证死的不是它。但记住,这是饮鸩止渴的另一种形式。
一句话总结
OOM Killer杀的是"最胖的",MySQL首当其冲;查dmesg确认凶手,治本靠加内存和限配额。别跟内核讲道理,它只认数字。下一篇讲IOPS vs 吞吐:买盘到底看哪个数字?