
Linux OOM Killer 触发不等于“内存全用光了”,而是内核判断当前已无安全可用内存——哪怕 free -h 显示还有几百 MB,只要低于 vm.min_free_kbytes 这条硬性水位线,且无法快速回收足够连续页,就会启动杀进程流程。
看日志确认是否真被 OOM Killer 杀掉
别只盯着 dmesg 里有没有 “Out of memory” 字样。最可靠的方式是:
- 运行
dmesg -T | grep -i "killed process",匹配到类似Out of memory: Killed process 12345 (java)的行,才是铁证 - 查
/var/log/messages(或 journalctl -k),搜索oom-killer或invoked oom-killer - 若日志中出现
Task in /mm_test killed as a result of limit of /mm_test,说明是 cgroup 内存超限触发,不是全局内存问题
查内存水位和关键参数
vm.min_free_kbytes 是决定 OOM 是否过早触发的核心参数:
- 它不是建议值,而是内核保障自身分配(如中断、驱动)不失败的硬性底线
- 64 位系统上误设为 1GB+(如 1024000)很常见,但合理值通常为总内存的 1% 左右(例如 32GB 内存设为 32768)
- 用
cat /proc/sys/vm/min_free_kbytes查当前值;临时调整用sysctl -w vm.min_free_kbytes=32768 - 注意:调太高会提前触发 OOM;调太低可能让内核分配失败,引发更隐蔽故障
区分是全局内存不足还是 cgroup 限制
日志里关键线索能直接定位根源:
- 如果显示
memory: usage 204800kB, limit 204800kB,说明某个 cgroup 达到硬限制(比如容器或 systemd scope) - 如果父 cgroup 被标出(如
limit of /mm_test,但进程在/mm_test/2),说明子组没超限,是父级资源被挤占 - 全局触发通常伴随
nodemask=0, order=0和无 cgroup 路径信息,且Cached:值高但释放滞后(如 JVM Full GC 突然要大块连续页)
别忽略 swap 和 page cache 的实际作用
很多人以为“开了 swap 就没事”,其实关键在是否来得及换出:
- swap 不是万能缓存,写回延迟高时,突发大内存申请仍可能来不及腾空间
-
Cached:高 ≠ 内存够用,因为 page cache 释放依赖 LRU + 回写队列,不能秒清 - 加 swap 是成本最低的缓解手段之一,尤其对偶发 spike 场景(如数据库 buffer 扩容、编译任务)
- 禁用 OOM Killer(
vm.oom_kill = 0)风险极大,会导致应用收到 NULL 指针或阻塞,比 kernel 主动杀更难诊断










