Comment tuer correctement MySQL?

28

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.logdossier, 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 le faire, killall -9 mysqlmais 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
Paul White dit GoFundMonica
la source

Réponses:

37

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 empêche une norme service mysql stopde fonctionner.

Il ne suffit pas de dire

mysqladmin -uroot -p -h127.0.0.1 shutdown

parce que mysqld acheminera un utilisateur entrant [email protected]vers root@localhostsi TCP / IP n'est pas explicitement activé. Par défaut, mysqld choisira le chemin le moins de résistance et de se connecter [email protected]à l' root@localhostaide du fichier socket. Pourtant, s'il n'y a pas de fichier socket, root@localhostne 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

De retour le 30 septembre 2011, j'ai scripté ma propre version de mysqld_multicalled 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. Il vous suffit d'apporter le vôtre my.cnfavec 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 c'est quoi ${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.1un port explicite. De cette façon, je ne compte pas sur un fichier socket.

J'ai toujours utilisé mysqladmin --protocol=tcp shtudowncomme alternative appropriée aux arrêts de mysql en cas de service mysql stopblocage. Faire kill -9sur mysqldet mysqld_safedevrait le dernier du 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 lancezshutdown . Cela doit fonctionner car le privilège d'arrêt est mysql.userréservé à des fins d'arrêt authentifiés. Cela a sauvé ma journée de travail à quelques reprises lorsque j'ai pu émettre un arrêt à distance depuis 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 vaut 1. Il y a 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.

RolandoMySQLDBA
la source
2
Le fichier de socket disparaît sur les dérivés de Red Hat car tmpwatchil le supprime, ainsi que tout le reste /tmpqui a un atime plus ancien que son seuil configuré.
Michael - sqlbot
Merci, @ Michael-sqlbot J'avais besoin d'entendre ça de quelqu'un, enfin. Je suppose que c'est pourquoi quelqu'un chez MySQL AB (pré-Oracle, pré-Sun) a décidé d'ajouter le privilège SHUTDOWN mysql.userpour contourner des maux de tête comme celui-ci.
RolandoMySQLDBA
Sur Debian ou Ubuntu, utilisez mysqladmin --defaults-file=/etc/mysql/debian.cnf shutdown... ce fichier contient des informations d'identification pour un compte MySQL de type root.
0xC0000022L
Comme d'habitude, @RolandoMySQLDBA, vous êtes l'une des meilleures ressources DBA sur les sites Stack Exchange. Excellent travail ici qui m'a aidé 6+ ans plus tard.
JakeGould
5

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;cet élément n ° 1, car vous devez avoir une idée de ce qui se passe sur votre serveur, ce qui rend l'arrêt si lent. S'il existe des requêtes de longue durée qu'il est sûr d'interrompre, vous pouvez les supprimer avec KILL <thread-id>.

Récapitulant les autres suggestions:

La 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 n'est cependant sûr que 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, celle-ci doit être définie sur 0.

L'utilisation FLUSH TABLES;gracieuse ferme 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 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 ne recevrez pas votre mysql>invite tant que vous ne posséderez pas ce verrou, auquel moment vous pourrez é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.

Michael - sqlbot
la source
2

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.

Valerie Parham-Thompson
la source
1

Je suis désolé d'entendre parler de votre expérience et j'espère que mon expérience avec des scénarios MySQL idiots, similaire à 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'intégrité 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 de Environnement CentOS / RHEL ):

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

Utilisez les éléments suivants pour identifier la charge système moyenne et les ressources les plus consommatrices au sein du système.

Vous devrez également procéder à l'installation mytoppour 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 prêt à utiliser 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 innotopsur un système moderne.

Michael Feng
la source
0

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, toujours en fonction de votre charge de travail, des configurations, de la mémoire disponible et des choix du 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 les 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.

LMC
la source