Avez-vous rencontré des temps de démarrage MySQL lents en mode GTID ? Nous avons récemment rencontré ce problème sur l'un de nos déploiements d'hébergement MySQL et nous avons décidé de le résoudre. Dans ce blog, nous expliquons le problème qui pourrait ralentir vos temps de redémarrage MySQL, comment déboguer votre déploiement et ce que vous pouvez faire pour réduire votre temps de démarrage et améliorer votre compréhension de la réplication basée sur GTID.
Comment nous avons trouvé le problème
Nous enquêtions sur les temps de démarrage lents de MySQL sur un déploiement MySQL 5.7.21 bas de gamme sur disque sur lequel le mode GTID était activé. Le système faisait partie d'une paire maître-esclave et était soumis à une charge d'écriture modérée. Lors du redémarrage lors d'une maintenance planifiée, nous avons remarqué que le serveur de base de données prenait 5 à 10 minutes pour démarrer et commencer à accepter les connexions. Ce type de retard n'avait pas de sens, nous avons donc décidé d'enquêter.
Débogage de votre heure de démarrage lente de MySQL
Nous avons utilisé l'outil Percona populaire pt-ioprofile pour voir ce que faisait la base de données. pt-ioprofil est un utilitaire très important dans la boîte à outils populaire de Percona qui est utilisé pour déboguer les problèmes de MySQL, et vous pouvez voir la liste complète des fonctionnalités dans leur documentation. Le pt-ioprofil l'outil utilise strace et lsof pour surveiller les E/S d'un processus et imprimer un tableau des fichiers et de l'activité des E/S.
Donc, nous avons démarré MySQL, attendu le mysqld processus pour être généré et démarré pt-ioprofile pour voir quel pourrait être le problème :
# pt-ioprofile --profile-process mysqld --run-time 200 Tue Oct 9 15:42:24 UTC 2018 Tracing process ID 18677 total pread read pwrite write fsync fdatasync open close getdents lseek fcntl filename ... 216.550641 0.000000 216.550565 0.000000 0.000000 0.000000 0.000000 0.000015 0.000040 0.000000 0.000021 0.000000 /mysql_data/binlogs/mysql-bin.000014 ...
Qu'est-ce qui ralentit le redémarrage de MySQL ?
En exécutant cela plusieurs fois, nous avons observé ce qui suit :
- Le mysqld Le processus passait la plupart de son temps à lire le dernier fichier journal binaire. C'était le cas même lorsque le serveur avait été arrêté correctement et qu'il n'était pas nécessaire de procéder à une reprise après incident, etc.
- Le serveur a également passé un temps considérable à charger les fichiers de données InnoDB, mais ce temps était beaucoup plus court par rapport au temps passé à lire le dernier fichier journal binaire.
- Si le serveur était redémarré immédiatement, ce redémarrage ultérieur serait beaucoup plus rapide.
- Étant donné qu'un arrêt de la base de données vide le journal binaire et en crée un nouveau au démarrage, nous avons fait une expérience supplémentaire :avant d'arrêter le serveur, nous avons vidé les journaux binaires. Le démarrage suivant du serveur a de nouveau été rapide.
Ces observations indiquaient clairement que MySQL passait beaucoup de temps à lire le dernier fichier journal binaire. Si le fichier était petit, comme ce serait le cas lorsque le fichier journal était vidé avant un arrêt, le démarrage était rapide.
Heure de démarrage de MySQL lente dans GTID ? La taille de votre fichier journal binaire peut être le problèmeCliquez pour tweeter
Comprendre la récupération de Binlog GTID
Il s'avère que pour remplir les valeurs de gtid_executed et gtid_purged, le serveur MySQL doit analyser les fichiers journaux binaires.
Voici le résumé de la recommandation de méthode de documentation MySQL 5.7 basée sur une lecture FAUX ou VRAI :
Lorsque binlog_gtid_simple_recovery =FAUX :
Pour calculer gtid_executed :
- Itérer les fichiers journaux binaires à partir du plus récent, en s'arrêtant au premier fichier contenant un Previous_gtids_log_event entrée.
- Consommer tous les GTID de Previous_gtids_log_event et Gtid_log_events à partir de ce fichier journal binaire et stocker cet ensemble GTID en interne. Il est appelé gtids_in_binlog.
- Valeur de gtid_executed est calculé comme l'union de gtids_in_binlog et les GTID dans la table mysql.gtid_executed .
Ce processus peut prendre beaucoup de temps s'il existe un grand nombre de fichiers journaux binaires sans GTID, par exemple, créés lorsque gtid_mode =OFF.
De même, pour calculergtid_purged :
- Itérer les fichiers journaux binaires du plus ancien au plus récent, en s'arrêtant au premier journal binaire contenant soit un événement Previous_gtids_log_event non vide (a au moins un GTID), ou qui a au moins un Gtid_log_event .
- Lire Previous_gtids_log_event à partir de ce fichier. Calculez la variable interne gtids_in_binlog_not_purged comme cet ensemble GTID soustrait de gtids_in_binlog.
- Valeur de gtid_purged est défini sur gtid_executed , moins gtids_in_binlog_not_purged .
Ainsi, cela constitue la base de notre compréhension de la façon dont les choses fonctionnaient dans les anciennes versions. Cependant, certaines optimisations peuvent être faites lorsque binlog_gtid_simple_recovery est vrai. C'est le cas qui nous intéresse :
Quand binlog_gtid_simple_recovery =VRAI :
(Notez qu'il s'agit de la valeur par défaut dans MySQL 5.7.7 et versions ultérieures)
- Lire uniquement les fichiers journaux binaires les plus anciens et les plus récents.
- Calculer gtid_purged de l'événement Previous_gtids_log_event ou Gtid_log_event trouvé dans le plus ancien fichier journal binaire.
- Calculer gtid_executed du Previous_gtids_log_event ou Gtid_log_event trouvé dans le fichier journal binaire le plus récent.
- Ainsi, seulement deux fichiers journaux binaires sont lus lors du redémarrage du serveur ou lors de la purge des journaux binaires.
Ainsi, pour les versions 5.7.7 et supérieures de MySQL, les fichiers journaux binaires les plus récents et les anciens sont toujours lus au démarrage du système pour initialiser correctement les variables système GTID. La lecture du fichier journal binaire le plus ancien n'est pas aussi coûteuse, car l'événement recherché par MySQL, Previous_gtids_log_event, est toujours le premier événement d'un fichier journal binaire.
Cependant, afin de calculer correctement gtid_executed , le serveur doit lire l'intégralité du dernier fichier journal binaire et collecter tous les événements de ce fichier. Ainsi, le temps de démarrage du système devient directement proportionnel à la taille du dernier fichier journal binaire .
Notez que la situation est encore pire lorsque binlog_gtid_simple_recovery est FAUX . Comme ce n'est plus l'option par défaut dans les versions récentes, ce n'est pas vraiment un problème.
Comment résoudre votre temps de démarrage lent
Après avoir compris la cause du problème que nous rencontrions, la solution que nous avons décidée était assez évidente :réduire la taille des fichiers journaux binaires. La taille par défaut des fichiers journaux binaires est de 1 Go. Il faut du temps pour analyser un fichier de cette taille au démarrage, il est donc logique de diminuer la valeur de max_binlog_size à une valeur inférieure.
Si la diminution de la taille du fichier journal binaire n'est pas une option, alors vider les fichiers journaux binaires juste avant un arrêt de maintenance du processus mysqld peut aider pour réduire les temps de récupération binlog GTID.