Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

Le progrès ne s'arrête pas, donc les raisons de mettre à jour vers les versions actuelles de MySQL deviennent de plus en plus pressantes. Récemment, dans l'un de nos projets, il était temps de mettre à jour nos confortables clusters Percona Server 5.7 vers la version 8. Tout cela se passait sur la plateforme Ubuntu Linux 16.04. Comment effectuer une telle opération avec un minimum d'interruption et quelles difficultés avons-nous rencontrées lors de la mise à jour — lisez cet article.

Préparation

Toute mise à jour d'un serveur de base de données est probablement liée à la reconfiguration de la base : modifications des exigences concernant les limites des ressources système et correction des configurations de la base, qui doivent être nettoyées des directives obsolètes.

Avant la mise à jour, nous consulterons obligatoirement la documentation officielle :

Et nous établirons un plan d'action :

  1. Corriger les fichiers de configuration en supprimant les directives obsolètes.
  2. Vérifier la compatibilité avec les outils.
  3. Mettre à jour les bases slaves en installant le paquet percona-server-server.
  4. Mettre à jour le maître en installant le même paquet.

Nous examinerons chaque point du plan et verrons ce qui pourrait mal tourner.

IMPORTANT ! La procédure de mise à jour du cluster MySQL basé sur Galera a ses spécificités, qui ne sont pas décrites dans cet article. Il ne faut pas utiliser cette instruction dans ce cas.

Partie 1 : Vérification des configurations

Dans la version 8 de MySQL, le query_cachea été supprimé. En réalité, il avait été déclaré obsolète déjà dans la version 5.7, mais maintenant, il est entièrement supprimé.Par conséquent, il est nécessaire de retirer les directives associées. Quant à la mise en cache des requêtes, nous pouvons maintenant utiliser des outils externes — par exemple, ProxySQL.

Il y avait aussi des directives obsolètes concernant innodb_file_format.Si dans MySQL 5.7, il était possible de choisir le format InnoDB, la version 8 fonctionne uniquement avec le format Barracuda..

Notre conclusion — suppression des directives suivantes :

  • query_cache_type, query_cache_limit et query_cache_size;
  • innodb_file_format. et innodb_file_format_max.

Pour la vérification, nous utiliserons l'image Docker de Percona Server. Nous placerons la configuration du serveur dans le répertoire mysql_config_test, et à côté, nous créerons des répertoires pour les données et les journaux. Exemple de test de configuration percona-server :

mkdir -p {mysql_config_test,mysql_data,mysql_logs}
cp -r /etc/mysql/conf.d/* mysql_config_test/
docker run --name some-percona -v $(pwd)/mysql_config_test:/etc/my.cnf.d/ -v $(pwd)/mysql_data/:/var/lib/mysql/ -v $(pwd)/mysql_logs/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -d percona:8-centos

En résumé : un fichier décrivant les directives problématiques apparaîtra dans les journaux Docker ou dans le répertoire des journaux, en fonction de votre configuration.

Voici ce que nous avions :

2020-04-03T12:44:19.670831Z 0 [Avertissement] [MY-011068] [Serveur] La syntaxe 'expire-logs-days' est obsolète et sera supprimée dans une future version. Veuillez utiliser binlog_expire_logs_seconds à la place.
2020-04-03T12:44:19.671678Z 0 [Avertissement] [MY-013242] [Serveur] --character-set-server : 'utf8' est actuellement un alias pour le jeu de caractères UTF8MB3, mais sera un alias pour UTF8MB4 dans une future version. Veuillez envisager d'utiliser UTF8MB4 pour éviter toute ambiguïté.
2020-04-03T12:44:19.671682Z 0 [Avertissement] [MY-013244] [Serveur] --collation-server : 'utf8_general_ci' est une collation du jeu de caractères obsolète UTF8MB3. Veuillez envisager d'utiliser UTF8MB4 avec une collation appropriée à la place.

Ainsi, nous avons également dû nous pencher sur les encodages et remplacer la directive obsolète expire-logs-days.

Partie 2 : Vérification des installations fonctionnelles

La documentation de mise à jour contient 2 utilitaires pour vérifier la compatibilité de la base. Leur utilisation aide l'administrateur à vérifier la compatibilité de la structure de données existante.

Commençons par l'utilitaire classique mysqlcheck. Il suffit de le lancer :

mysqlcheck -u root -p --all-databases --check-upgrade

Si aucun problème n'est détecté, l'utilitaire se terminera avec le code 0 :

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

En outre, dans les versions modernes de MySQL, il existe l'utilitaire mysql-shell (dans le cas de Percona, c'est le paquet percona-mysql-shell). Il remplace le client classique mysql et combine les fonctions d'un client, d'un éditeur de code SQL et d'outils d'administration MySQL. Pour vérifier le serveur avant la mise à jour, vous pouvez exécuter la commande suivante à travers elle :

mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=\/etc\/mysql\/my.cnf

Et voici les remarques que nous avons reçues :

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

Globalement, rien de critique — seulement des avertissements concernant les encodages (voir ci-dessous). Le résultat général de l'exécution :

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

Nous avons décidé que la mise à jour devrait se dérouler sans problème.

La remarque concernant les avertissements ci-dessus indique des problèmes avec les encodages. Le fait est qu'UTF-8 dans MySQL jusqu'à récemment n'était pas un 'véritable' UTF-8, car il ne stockait que 3 octets au lieu de 4. Dans MySQL 8, cela a enfin été corrigé: l'alias utf8 sera bientôt redirigé vers le jeu de caractères utf8mb4, tandis que les anciennes colonnes dans les tables deviendront utf8mb3. À l'avenir, le jeu de caractères utf8mb3 sera supprimé, mais pas dans cette version. C'est pourquoi nous avons décidé de corriger les encodages déjà sur l'installation active de SGBD, après sa mise à jour.

Partie 3 : Mise à jour des serveurs

Qu'est-ce qui pourrait mal tourner avec un plan aussi magnifique ?.. Tout en sachant que des détails inattendus peuvent survenir, nous avons d'abord réalisé notre première expérience sur un cluster MySQL dev.

Comme déjà mentionné, la documentation officielle aborde la question de la mise à jour des serveurs MySQL avec des répliques. L'essentiel est que d'abord, toutes les répliques (esclaves) devraient être mises à jour, car MySQL 8 est capable de répliquer à partir d'un maître en version 5.7. Une certaine complexité réside dans le fait que nous utilisons un mode master master, où le maître distant est en mode read-only. Ainsi, le trafic de production est dirigé vers un centre de données, tandis que le second est en secours.

La topologie se présente comme suit :

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

La mise à jour doit commencer par les répliques mysql replica dc 2, mysql master dc 2 et mysql replica dc 1, et se terminer par le serveur mysql master dc 1. Pour plus de fiabilité, nous avons arrêté les machines virtuelles, effectué des snapshots, puis juste avant la mise à jour, nous avons arrêté la réplication avec la commande STOP SLAVE. Pour le reste, la mise à jour se déroule comme suit :

  1. Nous redémarrons chaque réplique, en ajoutant dans les configurations trois options : skip-networking, skip-slave-start, skip-log-bin. En effet, la mise à jour de la base génère des logs binaires sur la mise à jour des tables système. Ces directives garantissent qu'aucune donnée d'application ne sera modifiée dans la base et que les logs binaires ne contiendront pas d'informations sur la mise à jour des tables système. Cela aidera à éviter des problèmes lors de la reprise de la réplication.
  2. Nous installons le paquet percona-server-server. Il est important de noter que dans la version MySQL 8, ne il est nécessaire d'exécuter la commande mysqlupgrade après la mise à jour du serveur.
  3. Après un démarrage réussi, nous redémarrons encore une fois le serveur — sans les paramètres ajoutés au premier point.
  4. Nous vérifions que la réplication fonctionne correctement : vérifions SHOW SLAVE STATUS et voyons que les tables avec les compteurs dans la base d'application sont mises à jour.

Tout cela semble assez simple : la mise à jour dev s'est bien passée. Ok, nous pouvons planifier tranquillement la mise à jour de nuit pour la production.

Sans ennui — nous avons mis à jour le prod

Cependant, le transfert d'une expérience réussie de dev à la production ne s'est pas déroulé sans surprises.

Heureusement, le processus de mise à jour commence par les répliques, donc, en rencontrant des difficultés, nous avons arrêté les travaux et restauré la réplique à partir du snapshot. L'enquête sur les problèmes a été reportée au matin suivant. Dans les logs, les enregistrements suivants se sont avérés :

2020-01-14T21:43:21.500563Z 2 [ERREUR] [MY-012069] [InnoDB] table: t1 a 19 colonnes mais le dictionnaire InnoDB a 20 colonnes
2020-01-14T21:43:21.500722Z 2 [ERREUR] [MY-010767] [Serveur] Erreur lors de la correction des données SE pour db1.t1
2020-01-14T21:43:24.208365Z 0 [ERREUR] [MY-010022] [Serveur] Échec de la population des tables DD.
2020-01-14T21:43:24.208658Z 0 [ERREUR] [MY-010119] [Serveur] Abandon

L'examen des archives de diverses newsletters sur Google a conduit à comprendre que ce problème survient à cause de un bug MySQL. Bien que cela soit plutôt un bug des utilitaires mysqlcheck et mysqlsh.

Il s'avère que MySQL a changé la façon de représenter les données pour les champs décimaux (int, tinyint, etc.), donc à l'intérieur de mysql-server une autre méthode est utilisée pour leur stockage. Si votre base de données était à l'origine dans la version 5.5 ou 5.1, puis vous avez mis à jour vers 5.7, il se peut que vous deviez effectuer un OPTIMIZE pour certaines tables. Dans ce cas, MySQL mettra à jour les fichiers de données en les convertissant au format de stockage actuel.

Vous pouvez également vérifier cela avec l'utilitaire mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # format du champ
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'your_decimal_column',
...

Si field_type votre valeur est 0, cela signifie qu'un ancien type est utilisé dans la table - il est nécessaire de procéder à un OPTIMIZE. Cependant, si la valeur est 246 - vous avez déjà un nouveau type. Vous pouvez en apprendre davantage sur les types dans le code.

De plus, dans ce bug une deuxième cause possible est examinée, qui nous a échappé - l'absence de tables InnoDB dans la table système INNODB_SYS_TABLESPACES, si ces tables ont été créées dans la version 5.1. Pour éviter des problèmes lors de la mise à jour, vous pouvez utiliser le script SQL ci-joint.

Pourquoi n'avons-nous pas rencontré de tels problèmes en dev ? La base est périodiquement copiée depuis la production - ainsi, les tables sont recréées.

Malheureusement, sur une grande base de données fonctionnelle, il n'est pas possible de faire simplement un OPTIMIZE. Cela peut être aidé par le percona-toolkit : pour l'opération OPTIMIZE en ligne, l'outil pt-online-schema-change convient parfaitement.

Le plan mis à jour est donc le suivant :

  1. Optimiser toutes les tables.
  2. Mettre à jour les bases de données.

Pour vérifier cela et en même temps déterminer le temps de mise à jour, nous avons désactivé l'une des répliques, et pour toutes les tables, nous avons exécuté la commande suivante :

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

La mise à jour des tables se fait sans blocages prolongés grâce à l'outil qui crée une nouvelle table temporaire dans laquelle les données sont copiées depuis la table principale. Au moment où les deux tables sont identiques, la table d'origine est bloquée et remplacée par la nouvelle. Dans notre cas, le lancement de test a montré qu'il faudrait environ 24 heures pour mettre à jour toutes les tables, mais en même temps, la copie des données causait une trop grande charge sur les disques.

Pour éviter cela, nous avons ajouté à la commande sur production l'argument --sleep avec une valeur de 10 — ce paramètre régule la durée d'attente après le transfert d'un lot de données dans la nouvelle table. Cela permet de réduire la charge si l'application réellement en cours d'exécution est exigeante en termes de temps de réponse.

Après l'optimisation, la mise à jour a réussi.

… mais pas complètement !

Déjà une demi-heure après la mise à jour, le client est venu avec un problème. La base fonctionnait de manière très étrange : des réinitialisations de connexions. Voici à quoi cela ressemblait dans le monitoring :

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

Le graphique en dents de scie visible sur la capture d'écran est lié au fait que certains threads du serveur MySQL tombaient périodiquement avec une erreur. Des erreurs sont apparues dans l'application :

[PDOException] SQLSTATE[HY000] [2002] Connection refused

Une inspection rapide des journaux a révélé que le démon mysqld ne pouvait pas obtenir les ressources nécessaires auprès du système d'exploitation. En analysant les erreurs, nous avons découvert dans le système des fichiers de politiques apparmor "orphelins":

# dpkg -S /etc/apparmor.d/cache/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/cache/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/local/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/local/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/usr.sbin.mysqld
mysql-server-5.7: /etc/apparmor.d/usr.sbin.mysqld
# dpkg -l mysql-server-5.7
rc  mysql-server-5.7 5.7.23-0ubuntu0.16.04.1      amd64

Ces fichiers se sont formés lors de la mise à jour vers MySQL 5.7 il y a quelques années et appartiennent à un paquet supprimé. La suppression des fichiers et le redémarrage du service apparmor ont résolu le problème :

systemctl stop apparmor
rm /etc/apparmor.d/cache/usr.sbin.mysqld
rm /etc/apparmor.d/local/usr.sbin.mysqld
rm /etc/apparmor.d/usr.sbin.mysqld
systemctl start apparmor

En conclusion

Toute opération, même la plus simple, peut entraîner des problèmes inattendus. Et même la possession d'un plan réfléchi ne garantit pas toujours le résultat escompté. Désormais, tous les plans de mise à jour de notre équipe incluent également un nettoyage obligatoire des fichiers inutiles qui ont pu apparaître à la suite des dernières actions.

Et avec cette création graphique pas très professionnelle, je voudrais remercier chaleureusement la société Percona pour ses excellents produits !

Mise à jour de MySQL (Percona Server) de 5.7 à 8.0

P.S.

Lisez aussi dans notre blog :

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster