OOM Killer - serveur MySQL tué

10

Sur l'un de nos maîtres MySQL, OOM Killer a été invoqué et tué le serveur MySQL, ce qui a entraîné une panne importante. Voici le journal du noyau:

[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

Cette machine a 64 Go de RAM.

Voici les variables de configuration mysql:

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

À l'exception de certains plugins nagios et scripts de collecte de mesures, rien d'autre ne s'exécute sur cette machine. Quelqu'un peut-il m'aider à savoir pourquoi le tueur OOM a été invoqué et comment puis-je l'empêcher d'être invoqué à l'avenir? Existe-t-il un moyen de dire au tueur OOM de ne pas tuer le serveur mysql. Je sais que nous pouvons définir une oom_adjvaleur très inférieure pour un processus afin d'éviter qu'il ne soit tué par le tueur OOM. Mais existe-t-il un autre moyen d'empêcher cela?

pradeepchhetri
la source
2
L'utilisation de la mémoire sera supérieure à 48G+ 512M+ 64Mcar il y a aussi des frais généraux et d'autres structures à considérer; il y avait une formule pour cela quelque part, mais je ne la trouve pas pour le moment. Je ne sais pas si cela le ferait exploser 64G. Juste pour vous assurer, freeconfirme que les 64Gsont disponibles en premier lieu?
frostschutz
@frostschutz: oui, la commande gratuite affiche 64G.
pradeepchhetri
Dire au tueur OOM de ne pas tuer mysqld ne fera que retarder la catastrophe d'un court instant. Mieux corriger votre configuration.
scai

Réponses:

25

Linux fait une surcharge de mémoire. Cela signifie qu'il permet au processus de demander plus de mémoire que ce qui est réellement disponible sur le système. Lorsqu'un programme essaie de malloc (), le noyau dit "OK vous avez la mémoire", mais ne la réservez pas. La mémoire ne sera réservée que lorsque le processus écrira quelque chose dans cet espace.

Pour voir la différence, vous avez 2 indicateurs: la mémoire virtuelle et la mémoire résidente. Virtual est la mémoire demandée par le processus, Resident est la mémoire réellement utilisée par le processus.

Avec ce système, vous pouvez passer en "surréservation", le noyau accorde plus de mémoire que disponible. Ensuite, lorsque votre système passe à 0 octet de mémoire libre et Swap, il doit sacrifier (tuer) un processus pour gagner de la mémoire libre.

C'est alors que OOM Killer entre en action. Le OOM sélectionne un processus basé sur sa consommation de mémoire, et bien d' autres éléments (gains parents 1/2 du score de ses enfants, si elle est un processus appartenant à la racine, le score est divisé par 4, etc .. Jetez un coup d' oeil sur Linux- MM.org/OOM_Killer

Vous pouvez influencer le score du MOO en optimisant le /proc/MySQL_PID/oom_adjfichier. En le définissant sur -17, votre processus ne sera jamais tué. Mais avant de faire cela , vous devez modifier votre fichier de configuration MySQL afin de limiter l'utilisation de la mémoire MySQL. Sinon, OOM Killer tuera les autres processus du système (comme SSH, crontab, etc ...) et votre serveur sera dans un état très instable, ce qui pourrait entraîner une corruption des données qui est pire que tout.

Vous pouvez également envisager d'utiliser plus de swap.

[ÉDITER]

Vous pouvez également modifier son comportement de sur-engagement via ces 2 systèmes:

vm.overcommit_memory
vm.overcommit_ratio

Comme indiqué dans la documentation du noyau

overcommit_memory:

Cette valeur contient un indicateur qui active le sur-engagement de mémoire.

Lorsque cet indicateur est 0, le noyau tente d'estimer la quantité de mémoire libre restante lorsque l'espace utilisateur demande plus de mémoire.

Lorsque cet indicateur est 1, le noyau prétend qu'il y a toujours suffisamment de mémoire jusqu'à ce qu'il soit réellement épuisé.

Lorsque cet indicateur est égal à 2, le noyau utilise une stratégie "ne jamais surcharger" qui tente d'empêcher toute surcharge de mémoire. Notez que user_reserve_kbytes affecte cette stratégie.

Cette fonctionnalité peut être très utile car de nombreux programmes utilisent malloc () d'énormes quantités de mémoire "juste au cas où" et n'en utilisent pas beaucoup.

La valeur par défaut est 0.

Voir Documentation / vm / overcommit-accounting et security / commoncap.c :: cap_vm_enough_memory () pour plus d'informations.

overcommit_ratio:

Lorsque overcommit_memory est défini sur 2, l'espace d'adressage engagé n'est pas autorisé à dépasser le swap plus ce pourcentage de RAM physique. Voir au dessus.

[/ÉDITER]

Adrien M.
la source
1
C'est la bonne réponse. J'ai vu des articles sur l'utilisation oom_score_adjde ce problème , mais ils ne comprennent pas vraiment le mécanisme du score.
3manuek