Что такое OOM Killer и когда он срабатывает
OOM Killer (Out Of Memory Killer) — механизм ядра Linux, который принудительно завершает процессы, когда оперативная память и swap заканчиваются одновременно. Ядро не может позволить системе зависнуть из-за нехватки памяти, поэтому выбирает "жертву" и убивает её сигналом SIGKILL. Чаще всего это происходит на VDS с 1-2 ГБ RAM без настроенного swap, когда MySQL, PHP-FPM или Java-приложение резко увеличивают потребление памяти.
Важно понимать: OOM Killer — это защитный механизм, а не баг. Если он сработал, системе реально не хватило памяти, и причину нужно искать в конфигурации сервисов или в объёме RAM.
Как узнать, что процесс убил именно OOM Killer
Если сервис неожиданно упал без явной ошибки в своём логе, проверьте системный журнал:
journalctl -k | grep -i "out of memory"
dmesg | grep -i oom
В выводе будет запись вида Out of memory: Killed process 1234 (mysqld) с указанием PID, имени процесса и количества занятой памяти на момент убийства. Так проще всего отличить OOM Killer от падения процесса по другой причине — например, ошибки сегментации.
Как найти процесс, который съедает память
Прежде чем настраивать защиту, найдите реального потребителя памяти. Быстрый способ — отсортировать процессы по использованию RAM:
ps aux --sort=-%mem | head -n 10
free -h
Команда free -h покажет общий объём памяти, занятую, свободную и размер swap. Без swap или при малом его размере любой скачок нагрузки — резервное копирование базы, всплеск трафика — мгновенно приводит к OOM. Подробно про настройку подкачки смотрите в статье про swap на VPS Linux.
Как ядро выбирает жертву: oom_score
Каждому процессу ядро присваивает значение oom_score — чем оно выше, тем вероятнее процесс убьют первым. Посмотреть текущий счёт можно так:
cat /proc/PID/oom_score
На счёт влияют объём занятой памяти, время работы процесса и явная настройка oom_score_adj, принимающая значения от -1000 до 1000. Значение -1000 полностью исключает процесс из кандидатов на убийство, а 1000 делает его первой мишенью.
Как защитить важный процесс от OOM Killer
Если на сервере есть сервис, который недопустимо убивать ни при каких условиях — скажем, основная база данных — понизьте его приоритет на убийство:
echo -900 > /proc/$(pidof mysqld)/oom_score_adj
Изменение действует только до перезапуска процесса. Чтобы закрепить настройку постоянно, добавьте параметр в unit-файл systemd сервиса:
[Service]
OOMScoreAdjust=-900
После правки выполните systemctl daemon-reload и перезапустите сервис. Защищая один процесс, вы автоматически повышаете риск для остальных — ядро всё равно найдёт, кого убить, при реальной нехватке памяти.
Профилактика: swap, лимиты памяти и мониторинг
Разовая настройка oom_score_adj не решает нехватку памяти — она лишь перекладывает риск на другой процесс. Реальная профилактика такая:
- Настройте swap-файл хотя бы 1-2 ГБ, чтобы сгладить кратковременные пики нагрузки.
- Ограничьте память тяжёлых сервисов явно:
memory_limitв PHP,innodb_buffer_pool_sizeв MySQL,-Xmxв Java. - Подключите мониторинг использования RAM, чтобы видеть рост потребления до срабатывания OOM — см. статью про мониторинг ресурсов VDS.
- Проверяйте журнал через
journalctl -kпосле каждого инцидента — подробнее в статье про journalctl и rsyslog. - При системной нехватке памяти правильный шаг — увеличить тариф VDS, а не бороться с симптомами.