web-dev-qa-db-fra.com

Comment tuer correctement MySQL?

J'ai CentOS 64 bits avec CPanel installé et j'utilise:

service mysql stop

Il ne fait que suivre les périodes et ne semble jamais s'arrêter. Dans les journaux, il affiche juste beaucoup de:

130303 17:42:38 [Warning] /usr/sbin/mysqld: Forcing close of thread

Dans le err.log fichier, j'en vois beaucoup:

[Warning] /usr/sbin/mysqld: Forcing close of thread

Avant, c'était instantané. Une idée pourquoi il fait cela et comment y remédier?

En ce moment, je dois faire killall -9 mysql Mais y a-t-il une meilleure façon?

Le serveur est également très très actif.

Est-ce un problème de configuration? Les paramètres de mémorisation sont-ils trop élevés?

[mysqld]
default-storage-engine=MyISAM
local-infile=0
symbolic-links=0
skip-networking
max_connections = 500
max_user_connections = 20
key_buffer = 512M
myisam_sort_buffer_size = 64M
join_buffer_size = 64M
read_buffer_size = 12M
sort_buffer_size = 12M
read_rnd_buffer_size = 12M
table_cache = 2048
thread_cache_size = 16K
wait_timeout = 30
connect_timeout = 15
tmp_table_size = 64M
max_heap_table_size = 64M
max_allowed_packet = 64M
max_connect_errors = 10
query_cache_limit = 1M
query_cache_size = 64M
query_cache_type = 1
low_priority_updates=1
concurrent_insert=ALWAYS
log-error=/var/log/mysql/error.log
tmpdir=/home/mysqltmp
myisam_repair_threads=4
[mysqld_safe]
open_files_limit = 8192
log-error=/var/log/mysql/error.log

[mysqldump]
quick
max_allowed_packet = 512M

[myisamchk]
key_buffer = 64M
sort_buffer = 64M
read_buffer = 16M
write_buffer = 16M
31
Tiffany Walker

Le moyen le plus simple d'arrêter mysql quand il le fait est simplement d'exécuter

mysqladmin -uroot -p -h127.0.0.1 --protocol=tcp shutdown

Voici pourquoi:

Le fichier de service mysql (/etc/init.d/mysql) repose sur la présence du fichier socket. Historiquement, remontant à MySQL 4.0, le fichier socket disparaît parfois inexplicablement. Cela entrave une norme service mysql stop de travailler.

Il ne suffit pas de dire

mysqladmin -uroot -p -h127.0.0.1 shutdown

parce que mysqld acheminera un utilisateur entrant en tant que [email protected] à root@localhost si TCP/IP n'est pas explicitement activé. Par défaut, mysqld choisira le moindre chemin de résistance et se connectera [email protected] à root@localhost via le fichier socket. Pourtant, s'il n'y a pas de fichier socket, root@localhost ne se connectera jamais.

Même la documentation MySQL sur mysqladmin dit ceci:

Si vous exécutez l'arrêt de mysqladmin lors de la connexion à un serveur local à l'aide d'un fichier socket Unix, mysqladmin attend que le fichier d'ID de processus du serveur soit supprimé, pour s'assurer que le serveur s'est arrêté correctement.

C'est pourquoi il est impératif d'activer TCP/IP:

mysqladmin -uroot -p -h127.0.0.1 --protocol=tcp shutdown

Le 30 septembre 2011, j'ai écrit ma propre version de mysqld_multi appelé mysqlservice (Voir mon article: Exécuter plusieurs instances sur le même hôte ). Il sert de moteur virtuel pour se connecter à mysqld à partir de différents ports. Vous n'avez qu'à apporter votre propre my.cnf avec des paramètres personnalisés. Dans ce script, j'émets des arrêts comme celui-ci:

stop() {
  ${ECHO} -n $"Stopping ${PROGNAME}"
  ${MYSQLD_STOP}
  ATTEMPTS=0
  STOPPING_MYSQLD=1
  MINUTES_TO_TRY=10
  (( TICKS_TO_TRY = MINUTES_TO_TRY*240 ))
  while [ ${STOPPING_MYSQLD} -eq 1 ]
  do
    ${ECHO} -n "."
    ${SLEEP} 0.25
    MYSQLD_HAS_BEEN_SHUTDOWN=`${TAIL} ${MYSQL_ERROR_LOG} | ${GREP} -c "Shutdown complete$"`
    (( ATTEMPTS++ ))
    if [ ${ATTEMPTS} -eq ${TICKS_TO_TRY}   ] ; then STOPPING_MYSQLD=0 ; fi
    if [ ${MYSQLD_HAS_BEEN_SHUTDOWN} -eq 1 ] ; then STOPPING_MYSQLD=2 ; fi
  done
  ${ECHO}
  if [ ${STOPPING_MYSQLD} -eq 2 ]
  then
    ${ECHO} "Stopped ${PROGNAME}"
  else
    ${TAIL} -30 ${MYSQL_ERROR_LOG}
  fi
}

Mais comment ça ${MYSQLD_STOP}?

MYSQL_CONN="-uroot -p<rootpassword> -P${MYSQLD_PORT} -h127.0.0.1 --protocol=tcp"
MYSQLD_STOP="${MYSQLADMIN} ${MYSQL_CONN} shutdown"

Veuillez noter que j'utilise 127.0.0.1 et un port explicite. De cette façon, je ne compte pas sur un fichier socket.

J'ai toujours utilisé mysqladmin --protocol=tcp shtudown comme alternative appropriée aux fermetures de mysql si service mysql stop bloque. Faire kill -9 sur mysqld et mysqld_safe doit être le dernier des derniers recours. (Oui, je l'ai dit trois fois).

Plusieurs fois, mysqld a supprimé mysql.sock sans avertissement. D'autres personnes ont également eu ce problème au fil des ans:

ÉPILOGUE

Le secret est comme je l'ai dit: Connectez-vous à mysql en utilisant mysqladmin via TCP/IP (--protocol=tcp) et lancez shutdown. Cela doit fonctionner car le privilège d'arrêt est dans mysql.user à des fins exclusives d'arrêts authentifiés. Cela a sauvé ma journée de travail à quelques reprises lorsque j'ai pu émettre un arrêt à distance à partir de ma machine Windows lors de l'arrêt de mysqld sur un serveur Linux.

MISE À JOUR 2013-03-06 22:48 EST

Si vous vous inquiétez de ce qui se passe pendant l'arrêt, il existe un moyen de manipuler le temps d'arrêt et la façon dont les données sont vidées sur le disque, surtout si vous avez beaucoup de données InnoDB dans le pool de tampons

SUGGESTION # 1

Si vous avez beaucoup de pages sales, vous pouvez réduire le innodb_max_dirty_pages_pct à 0:

SET GLOBAL innodb_max_dirty_pages_pct = 0;

Réglez-le environ 15 à 30 minutes avant l'arrêt. Cela donnera à mysqld le moins de pages sales à écrire sur le disque.

SUGGESTION # 2

Par défaut, innodb_fast_shutdown est 1. Il existe trois valeurs pour cette option

  • 0: InnoDB effectue un arrêt lent, une purge complète et une fusion de tampon d'insertion avant l'arrêt.
  • 1: InnoDB ignore ces opérations à l'arrêt, un processus appelé arrêt rapide.
  • 2: InnoDB vide ses journaux et s'arrête à froid, comme si MySQL s'était écrasé; aucune transaction validée n'est perdue, mais l'opération de récupération après incident rend le démarrage suivant plus long.

La documentation dit en outre ceci:

L'arrêt lent peut prendre des minutes, voire des heures dans les cas extrêmes où des quantités importantes de données sont toujours mises en mémoire tampon. Utilisez la technique d'arrêt lent avant la mise à niveau ou la rétrogradation entre les versions majeures de MySQL, afin que tous les fichiers de données soient entièrement préparés au cas où le processus de mise à niveau met à jour le format de fichier.

Utilisez innodb_fast_shutdown = 2 en cas d'urgence ou de dépannage, pour obtenir l'arrêt absolu le plus rapide si les données risquent d'être corrompues.

Les valeurs par défaut pour innodb_max_dirty_pages_pct et innodb_fast_shutdown devraient être très bien dans la plupart des cas.

38
RolandoMySQLDBA

Il semble que votre question porte moins sur "comment" arrêter MySQL et plus sur pourquoi le vôtre s'arrête si lentement.

Dans ma réponse à une question similaire , j'ai proposé quelques suggestions pour un redémarrage en douceur, qui aident en réduisant la quantité d'activité qui doit se produire après que vous ayez demandé à MySQL de commencer le processus d'arrêt .

Si vous n'êtes pas un utilisateur fréquent de SHOW FULL PROCESSLIST; c'est l'élément n ° 1, car vous devez avoir une idée de ce qui se passe sur votre serveur qui rend l'arrêt si lent. S'il existe des requêtes de longue durée pouvant être interrompues en toute sécurité, vous pouvez les supprimer avec KILL <thread-id>.

Récapitulant les autres suggestions:

Définition de la variable globale innodb_fast_shutdown = 1 (par défaut) accélérera la portion d'InnoDB de l'arrêt. Ceci est uniquement sûr, cependant, si vous arrêtez le serveur pour des raisons indépendantes de l'exécution d'une mise à niveau. Si vous arrêtez pour une mise à niveau, cela doit être réglé sur 0.

En utilisant FLUSH TABLES; ferme gracieusement toutes les tables ouvertes. Ils seront rouverts s'ils sont référencés par des requêtes ultérieures, mais cette action devrait toujours en fin de compte réduire le temps qui s'écoule entre le moment où vous demandez l'arrêt et le moment où l'arrêt est terminé, car il fait un peu de ménage et, plus important encore, il prépare le terrain pour la dernière étape ...

FLUSH TABLES WITH READ LOCK; ferme toutes les tables ouvertes et obtient un verrou exclusif appartenant à votre connexion client actuelle qui empêche toute autre connexion d'écrire sur une table sur l'ensemble du serveur. Vous n'obtiendrez pas votre mysql> Redémarrez jusqu'à ce que vous possédiez ce verrou, auquel moment vous pouvez émettre la demande d'arrêt - mais ne vous déconnectez pas de cette session.

Sur un serveur occupé, ces étapes devraient réduire le niveau d'activité sur le serveur, rendre les choses beaucoup plus silencieuses et aider à rendre l'arrêt ou le redémarrage plus fluide.

5
Michael - sqlbot

Il est probable que MySQL ne soit pas purement verrouillé, mais effectue des activités de nettoyage (rollbacks, etc.) lors de l'arrêt. Si vous ne le laissez pas faire tout cela lors de l'arrêt, vous devrez souvent attendre lors du démarrage.

Voici quelque chose à regarder: Arrêtez mysql dans une fenêtre de terminal tout en regardant le journal des erreurs (tail -f [yourerror.log]) dans une autre fenêtre de terminal. Le journal des erreurs vous montrera ce que fait MySQL.

Je suis désolé d'entendre parler de votre expérience et j'espère que mon expérience avec des scénarios idiots MySQL, similaires à celui-ci, pourra vous aider.

Au lieu d'essayer de comprendre comment supprimer le service MySQL du serveur, dans certains cas, vous devrez vérifier l'état de santé de votre système via les éléments suivants pour déterminer s'il y a un abus de service ( l'hypothèse est basée sur la notion d'un environnement CentOS/RHEL ):

 /usr/bin/iostat
 /usr/bin/uptime
 top -c

Utilisez ce qui suit pour identifier la charge système moyenne et les ressources les plus consommatrices au sein du système.

Vous devrez également installer mytop pour obtenir une vue d'ensemble des instructions SQL en cours de traitement par le système.

Pour installer mytop, procédez simplement comme suit:

 cd /root
 wget http://jeremy.zawodny.com/mysql/mytop/mytop-1.6.tar.gz
 tar -zxvf /root/mytop-1.6.tar.gz
 cd /root/mytop-1.6
 Perl Makefile.pl
 make
 make install
 chmod 644 /usr/local/bin/mytop
 vi /usr/local/bin/mytop 

(utilisez n'importe quel éditeur de texte que vous préférez)

Rechercher "long|!" => \$config{long_nums},

Commentez-le comme #"long|!" => \$config{long_nums},

chmod 555 /usr/local/bin/mytop

Et vous êtes bon pour aller avec mytop. Utilisez-le pour vérifier les instructions MySQL qui monopolisent votre service MySQL et les arrêter.

L'exécution des instructions ci-dessus vous fournira les capacités suivantes:

  • Diagnostic de l'état/de la santé de votre serveur
  • Diagnostic de votre cause de goulot d'étranglement

Une fois que vous avez éliminé la cause du goulot d'étranglement, vous devriez avoir une journée plus facile lorsque vous essayez de redémarrer le service MySQL. J'espère que vous trouverez les informations ci-dessus utiles.

Remarque:mytop est ancien et non entretenu. Vous devriez probablement utiliser innotop sur un système moderne.

1
Michael Feng

L'implémentation standard du script init de MySQL signale MySQL avec SIGTERM et attend un certain temps pour que MySQL s'arrête.

MySQL, après avoir reçu un SIGTERM, cessera d'abord de recevoir de nouvelles connexions, puis terminera l'exécution de toutes les requêtes encore en attente (cela peut prendre un certain temps, selon votre charge de travail et le nombre de clients simultanés), puis commencera à vider les données sur le disque (cela peut prendre longtemps, en fonction de votre charge de travail, de vos configurations, de la mémoire disponible et des choix de moteur de stockage). Une fois tous les vidages de données effectués, MySQL désallouera ensuite la mémoire allouée pendant la phase d'initialisation (cela peut également prendre un certain temps, selon la quantité de mémoire allouée par MySQL), fermera tous les descripteurs de fichiers encore ouverts, puis appellera "exit (0)".

Si après votre demande d'arrêt, MySQL met du temps à s'arrêter, il est fort possible qu'une ou plusieurs de ces étapes prennent du temps à se terminer. Si vous avez le temps, je vous recommande fortement d'attendre la fin du processus (cela évitera la perte de données ou de longs processus de récupération lorsque vous redémarrerez votre instance de base de données).

Malheureusement, votre question ne contient pas suffisamment d'informations pour me permettre de suggérer une solution appropriée à votre problème. J'espère que cela aide à comprendre le problème.

0
LMC