OOM Killer - убитый сервер MySQL

10

На одном из наших мастеров MySQL OOM Killer был вызван и убил сервер MySQL, что привело к большим сбоям. Ниже приведен журнал ядра:

[2006013.230723] mysqld invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[2006013.230733] Pid: 1319, comm: mysqld Tainted: P           2.6.32-5-amd64 #1
[2006013.230735] Call Trace:
[2006013.230744]  [<ffffffff810b6708>] ? oom_kill_process+0x7f/0x23f
[2006013.230750]  [<ffffffff8106bde2>] ? timekeeping_get_ns+0xe/0x2e
[2006013.230754]  [<ffffffff810b6c2c>] ? __out_of_memory+0x12a/0x141
[2006013.230757]  [<ffffffff810b6d83>] ? out_of_memory+0x140/0x172
[2006013.230762]  [<ffffffff810baae8>] ? __alloc_pages_nodemask+0x4ec/0x5fc
[2006013.230768]  [<ffffffff812fca02>] ? io_schedule+0x93/0xb7
[2006013.230773]  [<ffffffff810bc051>] ? __do_page_cache_readahead+0x9b/0x1b4
[2006013.230778]  [<ffffffff810652f8>] ? wake_bit_function+0x0/0x23
[2006013.230782]  [<ffffffff810bc186>] ? ra_submit+0x1c/0x20
[2006013.230785]  [<ffffffff810b4e53>] ? filemap_fault+0x17d/0x2f6
[2006013.230790]  [<ffffffff810cae1e>] ? __do_fault+0x54/0x3c3
[2006013.230794]  [<ffffffff812fce29>] ? __wait_on_bit_lock+0x76/0x84
[2006013.230798]  [<ffffffff810cd172>] ? handle_mm_fault+0x3b8/0x80f
[2006013.230803]  [<ffffffff8103a9a0>] ? pick_next_task+0x21/0x3c
[2006013.230808]  [<ffffffff810168ba>] ? sched_clock+0x5/0x8
[2006013.230813]  [<ffffffff81300186>] ? do_page_fault+0x2e0/0x2fc
[2006013.230817]  [<ffffffff812fe025>] ? page_fault+0x25/0x30

Эта машина имеет 64 ГБ оперативной памяти.

Ниже приведены переменные конфигурации mysql:

innodb_buffer_pool_size        = 48G
innodb_additional_mem_pool_size = 512M
innodb_log_buffer_size         = 64M

За исключением некоторых плагинов nagios и сценариев сбора метрик, на этом компьютере больше ничего не работает. Может ли кто-нибудь помочь мне выяснить, почему OOM killer был вызван и как я могу предотвратить его запуск в будущем. Есть ли способ, которым я могу сказать OOM Killer не убивать MySQL сервер. Я знаю, что мы можем установить oom_adjменьшее значение для процесса, чтобы предотвратить его уничтожение OOM killer. Но есть ли другой способ предотвратить это.

pradeepchhetri
источник
2
Использование памяти будет выше, чем 48G+ 512M+, 64Mпотому что есть также некоторые накладные расходы и другие структуры, которые следует учитывать; где-то была формула для этого, но сейчас я не могу ее найти. Не уверен, если это приведет к взрыву 64G. Просто чтобы удостовериться, хотя, freeподтверждает, что 64Gдоступны в первую очередь?
frostschutz
@frostschutz: да, бесплатная команда показывает 64G.
Pradeepchhetri
Сказать, что OOM Killer не убивает mysqld, скорее всего просто откладывает катастрофу на короткое время. Лучше исправить вашу конфигурацию.
Scai

Ответы:

25

Linux перегружает память. Это означает, что он позволяет процессу запрашивать больше памяти, чем реально доступно в системе. Когда программа пытается выполнить malloc (), ядро ​​говорит: «Хорошо, у вас есть память», но не резервируйте ее. Память будет зарезервирована только тогда, когда процесс будет что-то записывать в это пространство.

Чтобы увидеть разницу, у вас есть 2 индикатора: виртуальная память и резидентная память. Виртуальная - это память, запрошенная процессом, Resident - память, реально используемая процессом.

С этой системой вы можете перейти на «перебронирование», ядро ​​предоставляет больше памяти, чем доступно. Затем, когда ваша система переходит на 0 байт свободной памяти и выполняет обмен, он должен пожертвовать (убить) процессом, чтобы получить свободную память.

Именно тогда OOM Killer вступает в действие. OOM выбирает процесс, основываясь на потреблении памяти и многих других элементах (родитель получает половину оценки своих детей; если это процесс, принадлежащий пользователю root, оценка делится на 4 и т. Д. Посмотрите на Linux- MM.org/OOM_Killer

Вы можете повлиять на оценку OOM, настроив /proc/MySQL_PID/oom_adjфайл. Установив его -17, ваш процесс никогда не будет убит. Но прежде чем сделать это , вы должны настроить файл конфигурации MySQL , чтобы ограничить использование памяти MySQL. В противном случае OOM Killer убьет другие системные процессы (например, SSH, crontab и т. Д.), И ваш сервер будет работать в очень нестабильном состоянии, что может привести к повреждению данных, которое хуже всего.

Кроме того, вы можете рассмотреть возможность использования большего количества свопов.

[РЕДАКТИРОВАТЬ]

Вы также можете изменить его чрезмерное поведение через эти 2 sysctl:

vm.overcommit_memory
vm.overcommit_ratio

Как указано в документации ядра

overcommit_memory:

Это значение содержит флаг, который разрешает чрезмерное использование памяти.

Когда этот флаг равен 0, ядро ​​пытается оценить объем свободной памяти, когда пользовательское пространство запрашивает больше памяти.

Когда этот флаг равен 1, ядро ​​делает вид, что памяти всегда достаточно, пока она фактически не исчерпает себя.

Когда этот флаг равен 2, ядро ​​использует политику «никогда не перегружать», которая пытается предотвратить перегрузку памяти. Обратите внимание, что user_reserve_kbytes влияет на эту политику.

Эта функция может быть очень полезной, потому что есть много программ, которые malloc () занимают огромные объемы памяти «на всякий случай» и не используют ее много.

Значением по умолчанию является 0.

См. Documentation / vm / overcommit-accounting и security / commoncap.c :: cap_vm_enough_memory () для получения дополнительной информации.

overcommit_ratio:

Если для overcommit_memory задано значение 2, выделенное адресное пространство не может превышать объем подкачки плюс этот процент физической памяти. Смотри выше.

[/РЕДАКТИРОВАТЬ]

Адриен М.
источник
1
Это правильный ответ. Я видел статьи об использовании, oom_score_adjчтобы исправить это, но они не совсем понимают механизм оценки.
3manuek