禁用oom killer需配合memory cgroup隔离与oom_score_adj调优:启用memory cgroup、创建db_group并设memory.limit_in_bytes、echo 1 > memory.oom_control禁用其oom杀进程、设oom_score_adj=-1000降低全局oom时被杀概率。

直接禁用 OOM Killer 并不能保护数据库进程——它只会让系统在内存耗尽时彻底卡死或崩溃。真正有效的方式,是通过 memory cgroup 的 oom_kill_disable 控制 + 合理的 oom_score_adj 调整 + 内存限额隔离,让数据库进程既不被误杀,又不拖垮整机。
确认并启用 Memory Cgroup 支持
确保内核已启用 memory 子系统,且未被 GRUB 参数禁用:
- 检查配置:zcat /proc/config.gz | grep CONFIG_MEMCG,输出应为 CONFIG_MEMCG=y
- 确认未禁用:cat /proc/cmdline | grep cgroup_disable=memory,若出现该参数需从 GRUB 中移除
- 挂载 memory cgroup(若未自动挂载):mount -t cgroup -o memory none /sys/fs/cgroup/memory
为数据库进程创建独立 memory cgroup
避免数据库与其他服务混在同一 cgroup,防止“连带 OOM”:
- 新建控制组:mkdir /sys/fs/cgroup/memory/db_group
- 设置硬性内存上限(例如 4GB):echo 4G > /sys/fs/cgroup/memory/db_group/memory.limit_in_bytes
- 将数据库主进程(如 postgres、mysqld)PID 加入:echo $PID > /sys/fs/cgroup/memory/db_group/cgroup.procs
- 关键一步:禁用该 cgroup 的 OOM 杀死机制:echo 1 > /sys/fs/cgroup/memory/db_group/memory.oom_control(注意:此处写 1 表示 禁用 oom_kill,不是开启)
调整进程自身 OOM 优先级
即使在全局 OOM 触发时,也要降低数据库被选中的概率:
- 查看当前 oom_score_adj:cat /proc/$PID/oom_score_adj(默认为 0)
- 设为最低值(最不易被杀):echo -1000 > /proc/$PID/oom_score_adj
- 注意:该值仅对当前进程有效;若数据库由 systemd 启动,应在 service 文件中添加:OOMScoreAdjust=-1000
补充防护:关闭 swap 并监控内存压力
swap 会干扰 OOM 判定逻辑,且延迟内存紧张信号:
- 临时关闭:swapoff -a(生产环境建议保留少量 swap,但需调低 swappiness)
- 在 db_group 中限制交换倾向:echo 1 > /sys/fs/cgroup/memory/db_group/memory.swappiness
- 实时观察内存压力:watch -n1 'cat /proc/pressure/memory',重点关注 some.avg10 是否持续高于 50%
- 验证 OOM 状态:cat /sys/fs/cgroup/memory/db_group/memory.oom_control 应显示 oom_kill_disable 1 和 under_oom 0











