Forum Linux.général MySQL - oom killer

Posté par  . Licence CC By‑SA.
Étiquettes :
0
17
juin
2015

Bonjour à tous,

Je vous sollicite à nouveau pour un problème relativement complexe.

Samedi matin j'ai eu un "too many connection" bloquant mon applicatif sur MySQL (version = 5.5.40).
Mon max_connections est à 350 et rien n'explique encore une telle anomalie hormis un 'optimize' qui tournait et qui a peut être bloqué plusieurs bots.

J'ai donc killé tous les bots + toutes les sessions MySQL et nous étions repartis.

Mardi matin (hier donc), j'ai eu la désagréable surprise de constater que MySQL s'est fait killer par oom killer : out of memory. Est-ce la suite du samedi ? Bizarre mais pourquoi pas.
La machine physique est dédiée à MySQL et dispose de 256 Go de mémoire.

Voici un bout de la configuration (la partie intéressante pour la mémoire / les performances) :
key_buffer_size = 16M
max_allowed_packet = 100M
table_open_cache = 1000
table_definition_cache = 1000
sort_buffer_size = 20M
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
max_heap_table_size = 2G
tmp_table_size = 2G
max_connections = 350
query_cache_limit = 128M
query_cache_size = 2G
query_cache_type = 1
thread_cache_size = 2000
innodb_buffer_pool_size = 128G
innodb_additional_mem_pool_size = 4G
innodb_data_file_path = ibdata1:50M:autoextend:max:100G
innodb_log_file_size = 500M
innodb_log_buffer_size = 8M
innodb_log_files_in_group = 2
innodb_flush_log_at_trx_commit = 1
innodb_io_capacity = 200
innodb_file_per_table

D'après ce site http://www.omh.cc/mycnf/ j'ai besoin de 176 Go.
D'après ce site http://www.mysqlcalculator.com/ j'ai besoin de 151 Go.
J'avais également trouvé une règle de calcul mais je n'arrive pas à remettre la main dessus et j'étais plutôt à l'aise.

Le dmesg me dit que le kill a eu lieu à 23H50.
Si je regarde mes traitements, je constate plus un kill vers 00H31.
Les deux serveurs sont à l'heure (ntp toutes les heures).

Les deux seuls paramètres qui peuvent expliquer un pic de consommation sont tmp_table_size et max_heap_table_size puisqu'ils sont liés à une requête.
Par contre, s'il n'y a pas assez de mémoire pour assurer la mise en ram, j'ose espérer que MySQL flush sur disque. De plus, à l'heure du kill, je n'avais pas beaucoup de traitement (en tout cas rien qui explique que ce soit X tables temporaires ou X requêtes à jointures qui soient la cause du soucis).

Quand le service est tombé, j'étais en pleine sauvegarde : j'utilise déjà '--opt' (donc '--quick') vu que mes bases sont volumineuses. Ce qui signifie que normalement les lignes ne sont pas en ram mais directement flushées dans le dump.
J'ai redémarré le service hier matin et je suis resté à une consommation de 20% de la mémoire physique sur toute la journée. Quand le dump s'est déclenché hier soir, je suis monté à 65%. Depuis je ne descends plus.

Du coup, j'ai plusieurs questions :
- est-ce que MySQL pourrait ne pas avoir rendu la mémoire suite au kill des connexions ?
- qu'est-ce qui aurait pu causer cette consommation de mémoire alors que mes calculs tendent quand même à dire que j'ai une belle marge de sécurité ?
- qu'est-ce qui explique un décalage 23H50 (heure du kill dans dmesg) et 00H31 (heure réelle ou MySQL n'est plus) ?

Si quelqu'un a des idées / pistes à suivre je suis preneur.

Je vous remercie d'avance.

  • # Éviter le OOM

    Posté par  . Évalué à 2.

    Salut, Linux fourni de la mémoire en supposant qu’une partie des programmes ne vont pas l’utiliser, est donc qu’il n’aura pas à l’allouer réellement… C’est un comportement voulu. Voici un extrait de man malloc :

    By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. In case it turns out that the system is out of memory, one or more processes will be killed by the OOM killer. For more information, see the description of /proc/sys/vm/overcommit_memory and /proc/sys/vm/oom_adj in proc(5), and the Linux kernel source file Documentation/vm/overcommit-accounting.

    Il y a heureusement une façon de forcer Linux à allouer réellement la mémoire. Extrait de man proc :

    With strict overcommit enabled on the system (mode 2 /proc/sys/vm/overcommit_memory), allocations which would exceed the CommitLimit (detailed above) will not be permitted. This is useful if one needs to guarantee that processes will not fail due to lack of memory once that memory has been successfully allocated.

    En gros un petit echo 2 >/proc/sys/vm/overcommit_memory réglera le problème de l’OOM. Les logiciels seront notifié qu’il y a plus de mémoire. De là à dire qu’ils géreront correctement, je ne sais pas.

    • [^] # Re: Éviter le OOM

      Posté par  . Évalué à 1.

      Bonjour,

      Je te remercie pour la réponse mais en faites, dans l'idéal, j'aimerais comprendre ce qu'il s'est passé et non régler le soucis de l'oom. Il n'est pas logique que la consommation soit montée autant d'un coup :-(

      Déjà petit erratum : c'est pas 23H50 mais 2015-06-15T23:50:01,910825+0200 soit, si je ne me trompe pas, 00H50 et la c'est plus logique.

      Par contre je ne comprends par pourquoi la sauvegarde aurait tiré autant de RAM.
      Si quelqu'un a des informations la dessus je suis preneur.

      • [^] # Re: Éviter le OOM

        Posté par  . Évalué à 3.

        L’intérêt, c’est que l’application qui a besoin de RAM signalera peut-être dans les logs qu’elle n’a pas assez de RAM.

        • [^] # Re: Éviter le OOM

          Posté par  . Évalué à 1.

          Je suis d'accord avec toi mais j'ai deux soucis :
          - 1/ c'est une production très très critique : je ne peux pas jouer sans savoir comment ça va réagir
          - 2/ comme je n'arrive pas à reproduire le soucis, je ne peux pas le qualifier :(

          J'aurais pu désactiver le oom killer pour MySQL également mais si la machine s'effondre le soucis reste le même :-/

  • # Volumétrie

    Posté par  (site web personnel) . Évalué à 1.

    On peut avoir un peu plus de détails sur la volumétrie (quantité de données, nb de bases, nb de tables, moteur utilisé) ?

    Merci

    • [^] # Re: Volumétrie

      Posté par  . Évalué à 1.

      Oui alors il y a :
      - 2 "grosses" bases de données qui génèrent 99.9% de la charge
      - une dizaine de petites DB's mais qui ne sont pas beaucoup sollicitées
      - la première base c'est l'applicatif ; 190 Go sur disque ; 603 tables
      - la deuxième base c'est les logs ; 259 Go sur disque ; 13 tables
      - moteur = InnoDB dans les deux cas

      Pour donner une information complémentaire, depuis le redémarrage de MySQL :
      - toute la journée je suis resté à 20% de mémoire environ (ps aux)
      - la nuit, pendant les sauvegardes, je suis monté à 75%
      - le lendemain (donc hier) ça a continué de monté jusqu'à 80%
      - cette nuit, on est retombé à 68%

      On aurait pu penser qu'il s'agissait d'un soucis avec mysqldump mais j'ai lancé la même sauvegarde sur un des slave : la mémoire utilisée n'a pas bougée.

      J'ai revérifié les traitements qui tournaient dans ces heures la : rien de spécial. Et surtout il n'y a aucune modification de code qui pourrait expliquer une telle consommation.

      J'ai suivi la piste d'une attaque sur des sites (même s'ils ne sont pas référencés etc) : rien à déclarer.

      Du coup je me pose plusieurs questions :
      - fuite mémoire de MySQL ?
      - problème dans le kernel (3.18.9 hardened - Gentoo) ?
      - ma configuration qui n'est pas bonne (d'après toutes les règles de calcul on a de la marge)
      - suite logique des briquage de samedi ?

      Malheureusement je ne trouve aucune information nul part :-/

  • # sauvegarder sur le slave et comparer slave / master

    Posté par  (site web personnel) . Évalué à 1.

    On aurait pu penser qu'il s'agissait d'un soucis avec mysqldump mais j'ai lancé la même sauvegarde sur un des slave : la mémoire utilisée n'a pas bougée.

    Bon voilà une solution : faire la sauvegarde sur un slave (faut bien qu'ils servent à quelques choses ceux-là) ça limitera l'impact sur la prod.

    Également voir les différences de version et config entre le principal et les slaves.
    tu es sous gentoo, tu compiles mysql ?

    (et juste pour info, il te faut combien de temps pour dumper tes 190 Go ?)

    Mes 2¢

    • [^] # Re: sauvegarder sur le slave et comparer slave / master

      Posté par  . Évalué à 1.

      Avant on sauvegardait sur un slave mais en creusant un peu sur le net, nous avons lu plusieurs articles qui expliquent que les slave MySQL ne sont pas toujours consistants (même si 'SHOW SLAVE STATUS' te dit qu'il est à jour). Le Slave est là en cas de dernier recours mais dans la mesure du possible, nous ne lui faisons pas confiance et nous ne l'utilisons pas.
      D'ailleurs j'ai écarté la piste du dump en testant sur un slave : la consommation mémoire n'a pas bougée.

      Une seule ligne de différence entre notre master et notre slave : "read_only = 1" sur le slave.
      Version identique (5.5.40) des deux côtés. Les machines sont identiques mais dans deux datacentres différents.

      Il y a environ 1H / 1H15 de sauvegarde pour une base.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.