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 викликали і як я можу запобігти тому, щоб його викликали в майбутньому. Чи є якийсь спосіб я можу сказати вбивці OOM не вбивати сервер mysql. Я знаю, що ми можемо встановити oom_adjзначення вкрай менше для процесу, щоб не вбити його вбивцею OOM. Але чи є інший спосіб запобігти цьому.


2
Використання пам'яті буде вище 48G+ 512M+, 64Mтому що також слід враховувати деякі накладні та інші структури; Для цього десь була формула, але я зараз не можу її знайти. Не впевнений, чи це призведе до того, що це підірве 64G. Тільки для того, щоб переконатися, чи freeпідтверджує, що 64Gнаявні в першу чергу?
frostschutz

@frostschutz: так, безкоштовна команда показує 64G.
pradeepchhetri

Сказання вбивці OOM не вбивати mysqld дуже ймовірно просто затримає катастрофу на короткий момент. Краще виправте конфігурацію.
scai

Відповіді:


25

Linux перебормовує пам'ять. Це означає, що це дозволяє процесу вимагати більше пам’яті, ніж реально доступна в системі. Коли програма намагається malloc (), ядро ​​каже "Гаразд, ви отримали пам'ять", але не резервуйте її. Пам'ять буде зарезервована лише тоді, коли процес щось запише в цей простір.

Щоб побачити різницю, у вас є два індикатори: Віртуальна пам'ять та Резидентна пам'ять. Віртуальна - це пам'ять, яку вимагає процес, Resident - це пам'ять, реально використана процесом.

З цією системою ви можете перейти в "overbooking", ядро ​​надає більше пам'яті, ніж доступно. Потім, коли у вашій системі буде 0 байт вільної пам'яті та Swap, він повинен пожертвувати (вбити) процес для отримання вільної пам'яті.

Ось тоді вбивця OOM вступає в дію. OOM вибирає процес, виходячи з його споживання пам’яті та багатьох інших елементів (батько отримує 1/2 балів від своїх дітей; якщо це кореневий процес, оцінка ділиться на 4 тощо). Подивіться на Linux- MM.org/OOM_Killer

Ви можете вплинути на бал OOM, налаштувавши /proc/MySQL_PID/oom_adjфайл. Встановивши його -17, ваш процес ніколи не буде вбитий. Але перш ніж це зробити , слід налаштувати файл конфігурації MySQL , щоб обмежити використання пам'яті MySQL. В іншому випадку OOM Killer вбиває інші системні процеси (наприклад, SSH, crontab тощо), і ваш сервер буде в дуже нестабільному стані, можливо, це призведе до пошкодження даних, яке гірше всього.

Також ви можете скористатися більше свопом.

[EDIT]

Ви також можете змінити свою поведінку надмірно за допомогою цих двох систем:

vm.overcommit_memory
vm.overcommit_ratio

Як зазначено в Документації на ядро

overcommit_memory:

Це значення містить прапор, який дозволяє перевиконати пам'ять.

Якщо цей прапор дорівнює 0, ядро ​​намагається оцінити кількість вільної пам'яті, що залишилася, коли в просторі користувача потрібно більше пам'яті.

Коли цей прапор дорівнює 1, ядро ​​робить вигляд, що пам’яті завжди вистачає, поки його фактично не закінчиться.

Коли цей прапор дорівнює 2, ядро ​​використовує політику "ніколи не перевищувати", яка намагається запобігти будь-якому перевищенню пам'яті. Зауважте, що user_reserve_kbytes впливає на цю політику.

Ця функція може бути дуже корисною, оскільки існує багато програм, які малокомпонують () величезні обсяги пам’яті «про всяк випадок» і не використовують її багато.

Значення за замовчуванням - 0.

Додаткову інформацію див. У розділі Документація / vm / бухгалтерський облік та безпека / commoncap.c :: cap_vm_enough_memory ().

overcommit_ratio:

Коли для overcommit_memory встановлено значення 2, введений адресний простір заборонено перевищувати своп плюс цей відсоток фізичної оперативної пам’яті. Дивись вище.

[/ EDIT]


1
Це правильна відповідь. Я бачив статті, які використовують, oom_score_adjщоб виправити це, але вони не дуже розуміють механізм оцінки.
3manuek
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.