Траблшутинг падений MySQL по OOM: балансировка глобальных и сессионных буферов
- Процесс
mysqldвнезапно завершается ночью или при пиковых нагрузках без явных ошибок в mysql.log. - В выводе
dmesgилиjournalctl -kприсутствует записьOut of memory: Killed process (mysqld). - Сервер выделяет под InnoDB Buffer Pool более 80% RAM, не оставляя памяти для сессионных подключений.
1. Формула расчета максимального потребления памяти MySQL
Max_Memory_Usage = Global_Buffers + (max_connections * Per_Thread_Buffers)
Global_Buffers = innodb_buffer_pool_size + key_buffer_size + innodb_log_buffer_size
Per_Thread_Buffers = read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size + thread_stack + binlog_cache_size2. Корректировка буферов в /etc/mysql/my.cnf
[mysqld]
# Выделяйте под Buffer Pool не более 65-70% от общей RAM сервера
innodb_buffer_pool_size = 12G
innodb_buffer_pool_instances = 8
# Безопасные размеры сессионных буферов (не завышайте их!)
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
# Ограничение общего числа клиентов
max_connections = 300
max_heap_table_size = 64M
tmp_table_size = 64M3. Защита процесса через Systemd OOMScoreAdjust
Создайте оверрайд systemctl edit mysqld:
[Service]
OOMScoreAdjust=-900
LimitMEMLOCK=infinitysystemctl daemon-reload && systemctl restart mysqld Частые вопросы (FAQ)
Почему опасно выставлять sort_buffer_size в большие значения (например, 128MB)?
sort_buffer_size аллоцируется для КАЖДОГО потока, выполняющего сортировку ORDER BY/GROUP BY. 200 одновременных запросов с буфером 128MB мгновенно захватят 25GB RAM сверх Buffer Pool и вызовут OOM Killer.
Как в MySQL 8.0 ограничить суммарное потребление памяти компонентами?
Используйте глобальный параметр SET GLOBAL innodb_buffer_pool_size и контролируйте суммарное потребление через представление sys.memory_global_total.