Existe-t-il un redémarrage gracieux ou sûr pour mysql comme pour apache httpd?

29

Je voudrais redémarrer mysql gracieusement, tout comme httpd où les threads sont servis avant de redémarrer. Je ne voudrais pas que les requêtes soient interrompues.

giorgio79
la source

Réponses:

37

Toute séquence d'arrêt "demandée" dans MySQL (à court de kill -9) est quelque peu gracieuse , car les transactions en cours (sur les tables transactionnelles) sont annulées, mais voici quelques façons de rendre un redémarrage aussi propre que possible.

Remarque: si vous arrêtez le serveur pour une mise à niveau, n'utilisez pas ce processus; suivez plutôt le processus détaillé dans cette réponse .

Sinon, si vous redémarrez simplement un serveur autrement sain pour pouvoir modifier une variable globale en lecture seule ou quelque chose de similaire, voici un chemin gracieux:

Tout d'abord, activez innodb_fast_shutdownsi ce n'est pas déjà fait. Ce n'est pas directement lié à la grâce de l'arrêt, mais cela devrait ramener votre serveur plus rapidement.

mysql> SHOW VARIABLES LIKE 'innodb_fast_shutdown';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| innodb_fast_shutdown | 0     |
+----------------------+-------+
1 row in set (0.00 sec)

mysql> SET GLOBAL innodb_fast_shutdown = 1;
Query OK, 0 rows affected (0.01 sec)

Ensuite, demandez au serveur de fermer toutes les tables ouvertes dès qu'aucune requête en cours d'exécution ne les référence. Cette étape n'a également rien à voir avec l'arrêt progressif, mais elle accélérera l'étape suivante:

mysql> FLUSH LOCAL TABLES;
Query OK, 0 rows affected (41.12 sec)

L' FLUSH TABLESinstruction (avec le LOCALmot clé facultatif , qui évite un vidage inutile mais sinon inoffensif des esclaves) se bloquera et votre invite ne reviendra que lorsque toutes les tables pourront être fermées. Une fois que chaque table a été "vidée" (fermée), si une requête fait ensuite référence à la table, elle sera automatiquement rouverte, mais ce n'est pas grave. Ce que nous accomplissons avec cette étape, c'est faire moins de travail pour la dernière étape:

mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (13.74 sec)

mysql>

Cette instruction vide toutes les tables (d'où l'avantage d'en retirer une partie de manière moins perturbatrice avec l'étape précédente) et acquiert un verrou global (à l'échelle du serveur) en lecture seule sur elles.

Vous ne pouvez pas avoir un verrou de lecture global tant que chaque requête "écriture" en cours d'exécution (c'est-à-dire à peu près tout, mais SELECT) est terminée. L'émission de la demande de verrouillage permettra aux requêtes existantes de se terminer mais pas aux nouvelles de démarrer.

Votre invite ne revient pas tant que vous ne maintenez pas ce verrou global, donc chaque requête en cours lorsque vous demandez le verrou peut se terminer, et vous savez qu'elles sont terminées, car vous récupérez l'invite. Toutes les requêtes ultérieures qui tentent d'écrire quoi que ce soit dans n'importe quelle table seront simplement bloquées, ne modifiant aucune donnée, attendant indéfiniment le verrou, jusqu'à ce que ...

  • vous changez d'avis sur le redémarrage et libérez le verrou manuellement ( UNLOCK TABLES;)
  • vous redémarrez le serveur, ou
  • vous déconnectez accidentellement ou intentionnellement le client de ligne de commande de ce thread (alors ne le faites pas). Gardez cette fenêtre connectée et assis à l'invite mysql:

Résistez à la tentation de fermer cela.

mysql>

Cette invite de console inactive est ce qui détient le verrou global pour vous. Perdez cela, perdez le verrou.

À partir d'une autre fenêtre de console, redémarrez MySQL comme vous le feriez normalement, soit avec des scripts de démarrage (par exemple, votre variante locale de service mysql.server restart) soit avec mysqladmin shutdownsuivi d'un redémarrage manuel.

Michael - sqlbot
la source
L'utilisation innodb_fast_shutdown = 1garantit- elle vraiment que MySQL démarre plus rapidement? En regardant les documents, il semble que cela améliore la vitesse d'arrêt (au détriment de la vitesse de démarrage?).
Chris
@Chris l'idée est que cela aide à garantir que l'ensemble de l'arrêt + démarrage est aussi rapide que possible, mais c'est quelque peu anecdotique car la quantité de travail en cours est théoriquement la même - juste déplacée de l'autre côté de la séquence - mais pour une raison quelconque, cela a toujours semblé généralement plus rapide dans l'ensemble, comme peut-être qu'il y a une inefficacité dans la façon dont cela se produit à l'arrêt qui n'est pas là au démarrage. Dur à dire.
Michael - sqlbot
2

En bref, certaines des meilleures pratiques à prendre en compte avant d'arrêter MySQL sont:

  1. Confirmez l'instance que vous allez arrêter pour éviter d'arrêter une autre instance par erreur.
  2. Arrêtez la réplication si vous allez arrêter un esclave mysql> STOP SLAVE;.
  3. Rincez les pages sales à l'avance pour réduire le temps d'arrêt mysql> SET GLOBAL innodb_max_dirty_pages_pct = 0;.
  4. Vérifiez les requêtes de longue durée mysql> SHOW PROCESSLIST;, tuez-les mysql> kill thread_id;ou attendez qu'elles se terminent.
  5. Vider le pool de tampons à l'arrêt mysql> SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;et le recharger au démarrage # vi /etc/my.cnf innodb_buffer_pool_load_at_startup = ON pour réchauffer le pool de tampons.

Ensuite, après avoir confirmé les points précédents, vous pouvez redémarrer MySQL en toute sécurité shell$ service mysql restart

Pour plus de détails, consultez mon article Vérifiez-les avant d'arrêter MySQL!

Moll
la source
Pourquoi cela a-t-il été rejeté? Je ne sais pas assez pour reconnaître quelles commandes sont mauvaises, mais je veux savoir afin de pouvoir les éviter.
Jon
Je ne sais pas ce qui précède est une mauvaise commande. Je suis les étapes ci-dessus et tant de gens le font. Seule l'étape 4 doit être avec prudence, vous ne devez tuer aucune requête tant que vous n'êtes pas sûr de ce que vous faites, sinon, attendez la fin des longues requêtes. Essayez-le et si cela vous a aidé, votez-le, sinon, votez-le!
Moll