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

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

Les progrès ne s'arrêtent pas, c'est pourquoi les raisons de passer aux dernières versions de MySQL deviennent de plus en plus convaincantes. Il n'y a pas si longtemps, dans l'un de nos projets, il était temps de mettre à jour les confortables clusters Percona Server 5.7 vers la version 8. Tout cela s'est produit sur la plateforme Ubuntu Linux 16.04. Comment effectuer une telle opération avec un temps d'arrêt minimal et quels problèmes nous avons rencontrés lors de la mise à jour - lisez cet article.

Formation

Toute mise à jour du serveur de base de données est très probablement associée à une reconfiguration de la base de données : modification des exigences en matière de limites de ressources système et correction des configurations de base de données qui doivent être débarrassées des directives obsolètes.

Avant la mise à jour, nous nous référerons certainement à la documentation officielle :

Et élaborons un plan d'action :

  1. Corrigez les fichiers de configuration en supprimant les directives obsolètes.
  2. Vérifiez la compatibilité avec les utilitaires.
  3. Mettre à jour les bases de données esclaves en installant le package percona-server-server.
  4. Mettez à jour le maître avec le même package.

Examinons chaque point du plan et voyons ce qui pourrait mal tourner.

IMPORTANT! La procédure de mise à jour d'un cluster MySQL basé sur Galera a ses propres subtilités qui ne sont pas décrites dans l'article. Vous ne devez pas utiliser cette instruction dans ce cas.

Partie 1 : Vérification des configurations

MySQL a été supprimé dans la version 8 query_cache. En fait, il était déclaré obsolète de retour dans la version 5.7, mais maintenant complètement supprimé. Il est donc nécessaire de supprimer les directives associées. Et pour mettre en cache les requêtes, vous pouvez désormais utiliser des outils externes, par exemple : ProxySQL.

Dans la configuration également, il y avait des directives obsolètes concernant innodb_file_format. Si dans MySQL 5.7 il était possible de sélectionner le format InnoDB, alors la 8ème version fonctionne déjà uniquement au format Barracuda.

Notre résultat est la suppression des directives suivantes :

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

Pour vérifier, 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 du serveur Percona :

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

Conclusion : soit dans les journaux Docker, soit dans le répertoire contenant les journaux - en fonction de vos configurations - un fichier apparaîtra dans lequel les directives problématiques seront décrites.

Voici ce que nous avons eu :

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] The syntax 'expire-logs-days' is deprecated and will be removed in a future release. Please use binlog_expire_logs_seconds instead.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.

Ainsi, nous devions encore comprendre les encodages et remplacer la directive obsolète expire-logs-days.

Partie 2 : Vérification des installations en état de marche

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

Commençons par l'utilitaire classique mysqlcheck. Exécutez simplement :

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

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

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

De plus, un utilitaire est disponible dans les versions modernes de MySQL shell mysql (dans le cas de Percona, c'est le package percona-mysql-shell). Il remplace le client mysql classique 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 les commandes suivantes via celui-ci :

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

Voici les commentaires que nous avons reçus :

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

En général, rien de critique - seulement des avertissements concernant les encodages (voir ci-dessous). Résultat global de l'exécution :

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

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

Une note sur les avertissements ci-dessus indiquant des problèmes d'encodage. Le fait est que UTF-8 dans MySQL jusqu'à récemment n'était pas "vrai" UTF-8, puisqu'il ne stockait que 3 octets au lieu de 4. Dans MySQL 8, c'est finalement j'ai décidé de le réparer: pseudonyme utf8 mènera bientôt au codage utf8mb4, et les anciennes colonnes des tableaux deviendront utf8mb3. Encodage supplémentaire utf8mb3 sera supprimé, mais pas dans cette version. Par conséquent, nous avons décidé de corriger les encodages déjà sur l'installation du SGBD en cours, après l'avoir mis à jour.

Partie 3 : Mises à jour du serveur

Qu'est-ce qui pourrait mal se passer quand il existe un plan aussi intelligent ?... Comprenant très bien que des nuances surviennent toujours, nous avons mené la première expérience sur un cluster de développement MySQL.

Comme déjà mentionné, documentation officielle couvre la question de la mise à jour des serveurs MySQL avec des répliques. L'essentiel est que vous devez d'abord mettre à jour toutes les répliques (esclaves), puisque MySQL 8 peut répliquer à partir d'une version maître 5.7. Une difficulté réside dans le fait que l'on utilise le mode maître <-> maître, lorsque le maître distant est en mode en lecture seule. Autrement dit, le trafic de combat est dirigé vers un centre de données et le second est un centre de sauvegarde.

La topologie ressemble à ceci :

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

La mise à jour doit commencer avec les répliques réplique MySQL DC 2, maître mysql dc 2 и mysql replica dc 1, et terminons par le serveur mysql master dc 1. Pour être plus fiable, nous avons arrêté les machines virtuelles, en avons pris des instantanés, et juste avant la mise à jour, avons arrêté la réplication avec la commande STOP SLAVE. Le reste de la mise à jour ressemble à ceci :

  1. Nous redémarrons chaque réplique en ajoutant 3 options aux configs : skip-networking, skip-slave-start, skip-log-bin. Le fait est que la mise à jour de la base de données génère des journaux binaires avec des mises à jour des tables système. Ces directives garantissent qu'il n'y aura aucune modification des données d'application dans la base de données et que les informations sur la mise à jour des tables système ne seront pas incluses dans les journaux binaires. Cela évitera des problèmes lors de la reprise de la réplication.
  2. Installation du paquet percona-server-server. Il est important de noter que dans MySQL version 8 aucun tu dois exécuter la commande mysqlupgrade après la mise à jour du serveur.
  3. Après un démarrage réussi, nous redémarrons le serveur - sans les paramètres ajoutés dans le premier paragraphe.
  4. Nous nous assurons que la réplication fonctionne correctement : vérifiez SHOW SLAVE STATUS et vérifiez que les tables avec les compteurs dans la base de données de l'application sont mises à jour.

Tout semble assez simple : la mise à jour des développeurs a réussi. Ok, vous pouvez planifier en toute sécurité une mise à jour nocturne pour la production.

Il n'y avait pas de tristesse - nous avons mis à jour la production

Cependant, le transfert d’une expérience de développement réussie vers la production n’a pas été sans surprises.

Heureusement, le processus de mise à jour lui-même commence par les répliques. Ainsi, lorsque nous avons rencontré des difficultés, nous avons arrêté le travail et restauré la réplique à partir de l'instantané. L'enquête sur les problèmes a été reportée au lendemain matin. Les journaux contenaient les entrées suivantes :

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] table: t1 has 19 columns but InnoDB dictionary has 20 columns
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Error in fixing SE data for db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Failed to Populate DD tables.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Aborting

La recherche des archives de diverses listes de diffusion sur Google a permis de comprendre que ce problème est dû à Bogue MySQL. Bien qu'il s'agisse plus probablement d'un bug de l'utilitaire mysqlcheck и mysqlsh.

Il s'avère que MySQL a changé la façon dont ils représentent les données pour les champs décimaux (int, tinyint, etc.), donc mysql-server utilise une manière différente pour les stocker. Si votre base de données au début était en version 5.5 ou 5.1, puis vous avez mis à jour vers la version 5.7, vous devrez peut-être faire OPTIMIZE pour certains tableaux. Ensuite, MySQL mettra à jour les fichiers de données, en les transférant 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, # формат поля
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'you_deciaml_column',
...

si field_type Si vous l'avez égal à 0, alors l'ancien type est utilisé dans le tableau - vous devez effectuer OPTIMIZE. Cependant, si la valeur est 246, vous disposez déjà d’un nouveau type. Plus d’informations sur les types peuvent être trouvées dans code.

De plus, dans ce bug Nous envisageons la deuxième raison possible, qui nous a contourné : 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 les problèmes lors de la mise à jour, vous pouvez utiliser script SQL ci-joint.

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

Malheureusement, sur une grande base de données vraiment fonctionnelle, vous ne pourrez pas simplement prendre et exécuter une base de données universelle. OPTIMIZE. percona-toolkit vous aidera ici : l'utilitaire pt-online-schema-change est excellent pour l'opération OPTIMIZE en ligne.

Le plan mis à jour ressemblait à ceci :

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

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

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

Les tables sont mises à jour sans longs verrous car l'utilitaire crée une nouvelle table temporaire dans laquelle il copie les données de la table principale. Au moment où les deux tables sont identiques, la table d'origine est verrouillée et remplacée par la nouvelle. Dans notre cas, un test a montré qu'il faudrait environ une journée pour mettre à jour toutes les tables, mais la copie des données entraînait une charge trop importante sur les disques.

Pour éviter cela, en production nous avons ajouté l'argument à la commande --sleep avec une valeur de 10 - ce paramètre ajuste la durée d'attente après le transfert d'un lot de données vers une nouvelle table. De cette façon, vous pouvez réduire la charge si l'application en cours d'exécution est exigeante en termes de temps de réponse.

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

... mais pas complètement !

Une demi-heure après la mise à jour, le client a rencontré un problème. La base de données fonctionnait très étrangement : périodiquement, elle démarrait la connexion est réinitialisée. Voici à quoi cela ressemblait en monitoring :

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

La capture d'écran montre un graphique en dents de scie en raison du fait que certains threads du serveur MySQL plantaient 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 n'a pas pu obtenir les ressources requises du système d'exploitation. En triant les erreurs, nous avons découvert dans le système Fichiers de stratégie d'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 ont été créés lors de la mise à niveau vers MySQL 5.7 il y a quelques années et appartiennent à un package 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 avoir un plan bien pensé ne garantit pas toujours le résultat escompté. Désormais, tous les plans de mise à jour de notre équipe incluent également le nettoyage obligatoire des fichiers inutiles qui auraient pu apparaître à la suite d'actions récentes.

Et avec cette créativité graphique pas très professionnelle, je voudrais dire un immense merci à Percona pour leurs excellents produits !

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

PS

A lire aussi sur notre blog :

Source: habr.com

Ajouter un commentaire