## 症状现象
进程毫无征兆地消失:Java 服务半夜停了,PHP-FPM 偶发少几个子进程,MySQL 直接重启。系统日志里没有应用层的报错,像是被谁无声带走。此时先别急着怀疑程序 bug,内核的内存不足保护机制 OOM Killer 在内存耗尽时会挑一个占内存最多的进程直接杀掉,替整个系统续命。要确认是不是它干的,证据在内核日志里。
## 定位证据
两条命令看现场:
bash dmesg -T | grep -i -E "oom|killed process" grep -i oom /var/log/messages
dmesg -T 带人类可读时间戳。命中 OOM 的日志有固定特征:先是一段 Out of memory 字样的内存状态汇总,接着 Killed process 后面跟着进程名、PID 与它当时的内存占用、评分。把被杀时间与业务日志对齐,就能解释当时的报错或抖动。日志里还会附上各进程当时的内存占用与评分表,能看到内核为什么挑中它,评分越低的进程越安全。评分机制偏向杀占内存大的进程,所以被杀的常是 Java 或数据库这类大户,这不是它们的错,是它们块头大。
## 分析水位再决策
确认 OOM 之后,回答一个问题:是瞬时峰值还是持续泄漏。看监控曲线最直观:free 的 available 长期缓慢单调下降,几周爬到枯竭,是泄漏或缓存无上限,方向是查程序;曲线平时平稳,只在某个时点尖峰,比如夜间备份、大促流量、批量任务,是容量不足或任务集中,方向是错峰或限内存。临时缓解可以把关键服务的内存上限写进 systemd 单元,用 MemoryMax 拴住它,让 OOM 在预算内挑对象,不误伤数据库。
## 预防建议
内存要有水位管理:可用率常态保持三成以上,低于两成就该行动。在顺云控制台给内存使用率配告警,比 OOM 之后再翻日志主动得多;swap 做最后缓冲,争取处置时间而不是常态依赖。升级内存前先想清楚是业务真涨了还是程序漏了,前者升配解决,后者升配只是把死刑改缓期。每次 OOM 事件都留下 dmesg 片段与当时监控截图归档,积累几次就能看出规律。容器化环境还要分清两层账本:容器组限额与宿主机内存是两回事,容器内看着宽裕,宿主机可能已经告急。