Что было. Сайт на WordPress с посещаемостью около 150 просмотров в день на виртуальной машине с 512 МБ памяти. MySQL периодически падал, в системном журнале ядро сообщало об убийстве процесса mysqld из-за нехватки памяти, а в журнале MySQL: InnoDB: mmap(137363456 bytes) failed; errno 12 и Fatal error: cannot allocate memory for the buffer pool.
Почему. Стандартная конфигурация MySQL резервирует 128 МБ только под буферный пул InnoDB, к этому добавляются буферы соединений, рабочие процессы веб-сервера и PHP. На 512 МБ всё это не помещается, и при первом всплеске запросов ядро убивает самый «тяжёлый» процесс: базу данных. Нагрузка ни при чём, дело в размерах по умолчанию.
Что предложили и что помогло.
- Файл подкачки на 1 ГБ. Снял аварии сразу и дал время на настройку. Это подушка, а не решение: база на подкачке работает медленно.
- Уменьшить
innodb_buffer_pool_size(например до 64 МБ для такого сайта) иmax_connections; выключить неиспользуемые механизмы хранения. - Ограничить число рабочих процессов веб-сервера и PHP-FPM (
pm.max_children), потому что каждый из них при пике держит десятки мегабайт. - Проверить, не гонит ли кто-то нагрузку извне: в похожих обсуждениях причиной оказывались автоматические запросы к XML-RPC WordPress.
Как понять, что вас убил именно OOM. journalctl -k | grep -i "out of memory" покажет, какой процесс и когда; free -m в момент проблемы, а лучше короткий скрипт, пишущий free -m раз в минуту в файл, чтобы увидеть рост.
Правило для маленьких машин. Сумма пределов памяти всех служб должна быть меньше физической памяти с запасом на кэш файловой системы. Если после настройки база всё равно не помещается, дешевле добавить памяти машине, чем терять данные при аварийных остановках.
Статус. Подкачка помогла автору как временная мера, дальнейшая настройка в обсуждении не подтверждена.
Размер буферного пула описан в документации MySQL.