Pourquoi Apache fonctionne-t-il de manière sauvage et tue-t-il MySQL?

8

Apache a perdu le contrôle au cours des derniers jours et a fait planter MySQL deux fois. Tout a commencé lorsque j'ai migré un site WordPress sur lequel contient également un forum phpBB.

Je ne suis pas très expérimenté en administration de serveur, il m'a donc été très difficile d'identifier la cause du problème. Quand j'ai remarqué que MySQL était en panne, j'ai exécuté TOP et j'ai vu mon pic de charge système à 98,00. Le serveur exécute 10 V-HOSTS qui reçoivent tous une bonne quantité de trafic, donc je voyais évidemment de nombreux processus apache-2 en cours d'exécution.

La charge élevée du serveur s'est poursuivie pendant 10 minutes, puis elle est revenue à un état normal. Je n'ai pas vu de pointe de trafic réseau à ce stade.

Malheureusement, la journalisation des erreurs MySQL a été désactivée (elle est maintenant réactivée), donc aucun indice là-bas. Mais je suis sûr que c'est parce qu'Apache consommait toutes les ressources, donc l'ID de processus MySQL a été tué.

Mes questions sont:

La prochaine fois que cela se produira - comment puis-je identifier la cause du pic de charge du système? Serait-ce un script php devenu fou? Serait-ce une attaque DDOS?

Existe-t-il un moyen de redémarrer automatiquement MySQL lorsqu'il se bloque?

J'ai maintenant installé htop. Cela pourrait-il être plus utile que top?

Voici mes statistiques de serveur:

m1.xlarge (8 ECUs, 4 vCPUs, 15 GiB memory, 4 x 420 GiB Storage Capacity)
Ubuntu Server 12.04.3 LTS 
Bob Flemming
la source
Bien que les journaux aient été désactivés, cela dmesgaiderait-il?
Daniel W.

Réponses:

9

MySQL peut toujours ne rien enregistrer, car ce qui se passe probablement, c'est qu'il est tué sans cérémonie par le système en raison de la pression sur la mémoire système des enfants d'Apache. Il devrait y avoir une trace de ceci dans / var / log / syslog.

MySQL devrait essayer de se redémarrer en cas de plantage ou d'arrêt forcé, mais à moins que suffisamment de mémoire ne soit disponible, il ne peut pas le faire ... et ce deuxième échec n'est pas vu par mysqld_safe comme un "plantage" mais plutôt comme un "refus de ", il ne continuera donc pas à essayer. La tentative de redémarrage a échoué est souvent mal interprétée par les administrateurs comme le «plantage», car la nature de l'échec d'origine est cachée derrière un message facilement ignoré dans le journal des erreurs MySQL:

mysqld_safe Number of processes running now: 0

Voir InnoDB Crash Post Mortem pour une circonstance que je soupçonne est similaire à la vôtre.

La réponse apparemment simple à "pourquoi" est qu'entre Apache et MySQL, la charge que vous avez et vos configurations actuelles, vous n'avez pas assez de mémoire sur la machine, et il y a un point de basculement lié à la charge de trafic qui fait sortir cette condition .

Apache sert chaque demande de navigateur simultanée à partir d'un processus enfant, donc du nombre de connexions simultanées augmente, le nombre d'enfants augmentera. Vous devrez d'abord limiter cette valeur dans la configuration d'apache afin que vous puissiez comprendre ce qui cause réellement l'augmentation des connexions simultanées ... est-ce simplement un pic de trafic lourd mais légitime? Une sorte de déni de service? Les requêtes de base de données qui retardent les demandes parce qu'elles s'exécutent trop longtemps? Quelque chose à optimiser?

http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxclients

Limiter les processus Apache simultanés devrait aider à éviter cela, mais pour être clair, il est naïf de penser que c'est la solution complète, donc je ne veux pas impliquer cela. Une fois que les processus sont limités à un niveau raisonnable ou au moins plus sûr, vous pouvez procéder à l'identification de ce qui se passe réellement. (Il existe d'autres contrôles de restriction sur Apache, mais ce n'est pas mon domaine d'expertise.)

La "meilleure pratique" est bien sûr d'exécuter votre base de données sur un matériel différent afin que l'application ne puisse pas le tuer. Bien qu'il semble plus efficace, à première vue, de "maximiser l'utilisation" d'une machine en la partageant, il s'agit d'une fausse économie. La majorité de la mémoire utilisée par MySQL, dans une charge de travail typique, est allouée au démarrage et conservée aussi longtemps que MySQL Server est en cours d'exécution. Les demandes sur le CPU sont susceptibles de partager des heures de pointe pour MySQL et Apache, car elles servent finalement la même charge. Vous pourriez en fait être mieux avec deux machines m1.large au lieu de la seule m1.xlarge, et le coût serait le même puisque la plus petite est exactement la moitié du prix de la plus grande ... même si vous avez déjà payé à l'avance pour la remise supplémentaire, ce changement peut être accompli .

Michael - sqlbot
la source
Merci pour votre réponse, c'était vraiment utile. J'ai vérifié / ver / log / syslog et j'ai trouvé les lignes suivantes: 18 décembre 15:48:38 ip-10-33-164-173 noyau: [29714591.071719] Mémoire insuffisante: processus de destruction 28369 (mysqld) note 21 ou sacrifice enfant 18 décembre 15:48:38 ip-10-33-164-173 noyau: [29714591.071753] Processus tué 28369 (mysqld) total-vm: 2520332kB, anon-rss: 335304kB, file-rss: 0kB Vous pensez donc limiter le La configuration de maxclients dans Apache est-elle la meilleure solution pour éviter que cela se produise? Selon vous, quelle serait une valeur plus sûre?
Bob Flemming
1
Je dirais que limiter les maxclients serait le meilleur moyen de commencer le processus de compréhension des circonstances qui contribuent à l'avalanche que vous rencontrez. Vous devrez déterminer une valeur plus sûre en fonction de votre situation, de la quantité de mémoire libre sur le système et de la quantité de mémoire typique que vous observez avec les enfants Apache. Trop faible et les demandes commenceront à être sauvegardées; trop haut et vous êtes où vous êtes maintenant. Surveillez ensuite les processus générés et observez la mémoire disponible et les journaux du serveur.
Michael - sqlbot
1

Vous avez quelques points à vérifier:

-Vérifiez le / var / log / messages: oomkiller peut tuer le processus mysql s'il n'y a plus de mémoire à utiliser. Vérifiez le ram avec -lm gratuit (sans cache)

-Si vous utilisez apache avec prefork mpm: vérifiez le nombre de processus. Si apache empile un nombre important de processus (lors d'une lourde charge de travail) avec un lien vers mysql, la latence et la mémoire utilisée peuvent rapidement augmenter.

-Vérifiez le nombre de threads lancés par mysql avec un statut global show : threads_cached, threads_created et threads_running sont importants à vérifier (threads_created doit être proche de 0).

-Vérifiez le bélier utilisé par Mysql.

Jérémy Munoz
la source
0

Vous pouvez également étudier l'implémentation de cpusets et la réservation de ressources pour mysql. C'est le plus proche de l'exécution de ces services sur un matériel différent, tout en vous offrant toujours les avantages de la maintenance d'un serveur unique.

skohrs
la source