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



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

Entraînement


Toute mise à jour du serveur de base de données est très probablement liée à la migration de la base de données: changements dans les exigences de limites sur les ressources système et la correction des configurations de base de données, qui doivent être débarrassées des directives obsolètes.

Avant la mise à jour, nous allons certainement nous tourner vers la documentation officielle:


Et faites 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. Mettez à jour les bases de données esclaves en installant le package percona-server-server.
  4. Mettez à jour l'assistant en mettant le même package.

Nous analyserons chaque élément du plan et verrons ce qui peut mal tourner.

IMPORTANT! La procédure de mise à niveau du cluster MySQL basée 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


Dans la version 8, MySQL a été supprimé query_cache. En fait, il a été déclaré obsolète dans la version 5.7, mais il est maintenant complètement supprimé . En conséquence, il est nécessaire de supprimer les directives connexes. Et pour la mise en cache des requêtes, vous pouvez désormais utiliser des outils externes - par exemple, ProxySQL .

Des directives pro obsolètes ont également été trouvées dans la configuration innodb_file_format. Si dans MySQL 5.7 il était possible de sélectionner le format InnoDB, alors la 8ème version ne fonctionne déjà qu'avec le format Barracuda .

Notre résultat est la suppression des directives suivantes:

  • query_cache_type, query_cache_limitet query_cache_size;
  • innodb_file_formatet innodb_file_format_max.

Pour vérification, nous utiliserons l'image Docker de Percona Server. Nous allons mettre la configuration du serveur dans le répertoire mysql_config_testet créer ensuite les répertoires pour les données et les journaux. Exemple de test de configuration de 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

Résultat: soit dans les journaux Docker, soit dans le répertoire avec les journaux - selon vos configurations - un fichier apparaîtra dans lequel les directives du problème seront décrites.

Voici ce que nous avions:

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 gérer les encodages et remplacer la directive obsolète expire-logs-days.

Partie 2: Vérification des installations en cours d'exécution


Il existe 2 utilitaires dans la documentation de mise à jour pour 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:



De plus, l'utilitaire mysql-shell est disponible dans les versions modernes de MySQL (dans le cas de Percona, il s'agit d'un package percona-mysql-shell). Il remplace le client mysql classique et combine les fonctions du client, de l'éditeur SQL et des 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

Et voici les commentaires que nous avons reçus:



En général, rien de critique - juste des avertissements sur les encodages (voir ci-dessous) . Le résultat global de l'implémentation:



nous avons décidé que la mise à jour se passerait sans problème.

Une note sur les avertissements ci-dessus qui indiquent des problèmes d'encodage. Le fait est que UTF-8 dans MySQL jusqu'à récemment n'était pas un "vrai" UTF-8 , car il ne stockait que 3 octets au lieu de 4. Dans MySQL 8, ils ont finalement décidé de le corriger : l'alias utf8conduira bientôt au codage utf8mb4, et les anciens les colonnes dans les tableaux deviendront utf8mb3. À l'avenir, l'encodage utf8mb3sera supprimé, mais pas dans cette version. Par conséquent, nous avons décidé de corriger les encodages déjà sur une installation de travail du SGBD, après l'avoir mise à jour.

Partie 3: Mises à jour du serveur


Qu'est-ce qui peut mal tourner quand il y a un plan aussi chic? .. Bien conscient que les nuances se produisent toujours, nous avons mené la première expérience sur le dev-cluster MySQL.

Comme déjà mentionné, la documentation officielle met en évidence le problème de la mise à jour des serveurs MySQL avec des répliques. L'essentiel est qu'au début, cela vaut la peine de mettre à jour toutes les répliques (esclaves), car MySQL 8 peut se répliquer à partir de l'assistant de la version 5.7. Une certaine difficulté réside dans le fait que nous utilisons le mode maître <-> maître lorsque le maître distant est en mode lecture seule . En fait, le trafic de combat entre dans un centre de données et le second est une sauvegarde.

La topologie est la suivante: la



mise à niveau doit commencer avec les répliques mysql replica dc 2, mysql master dc 2 et mysql replica dc 1, et se retrouvant avec le serveur mysql master dc 1. Pour une meilleure fiabilité, nous avons arrêté les machines virtuelles, leur avons fait des instantanés et arrêté la réplication avec la commande juste avant la mise à jour STOP SLAVE. Le reste de la mise à jour ressemble à ceci:

  1. Chaque redémarrage réplique, en ajoutant l'option de configuration 3: 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 mise à jour des tables système. Ces directives garantissent qu'aucune modification ne sera apportée aux 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 entrées dans les journaux binaires. Cela évitera des problèmes lors de la reprise de la réplication.
  2. Installez le package percona-server-server. Il est important de noter que dans MySQL 8, vous n'avez pas besoin d'exécuter la commande mysqlupgradeaprès la mise à jour du serveur.
  3. Après un démarrage réussi, redémarrez le serveur à nouveau - déjà sans les paramètres qui ont été ajoutés dans le premier paragraphe.
  4. Nous nous assurons que la réplication fonctionne correctement: nous vérifions SHOW SLAVE STATUSet voyons que les tables avec des compteurs dans la base de données d'application sont mises à jour.

Tout cela semble assez simple: la mise à jour du développeur a réussi. Ok, vous pouvez planifier en toute sécurité une mise à niveau du jour au lendemain pour la production.

Il n'y avait aucune tristesse - nous avons mis à jour prod


Cependant, le transfert de l'expérience de développement réussie à la production n'était pas sans surprises.

Heureusement, le processus de mise à jour lui-même commence par des répliques. Par conséquent, ayant rencontré des difficultés, nous avons arrêté le travail et restauré la réplique à partir de l'instantané. L'étude du problème a été reportée le lendemain matin. Les entrées suivantes sont apparues dans les journaux:

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

Une étude des archives de diverses listes de diffusion sur Google a permis de comprendre qu'un tel problème se produit en raison d'un bogue MySQL . Bien que ce soit même un bug utilitaire mysqlchecket mysqlsh.

Il s'avère que MySQL a changé la façon dont les données sont présentées pour les champs décimaux (int, tinyint, etc.), donc une autre façon de les stocker est utilisée dans mysql-server. Si votre base de données était à l'origine dans la version 5.5 ou 5.1, puis que vous avez effectué une mise à niveau vers 5.7, vous devrez peut-être produire OPTIMIZEdes tables. Ensuite, MySQL mettra à jour les fichiers de données, 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_typevous avez 0, l'ancien type est utilisé dans le tableau - cela doit être fait OPTIMIZE. Cependant, si la valeur est 246, vous avez déjà un nouveau type. Plus d'informations sur les types peuvent être trouvées dans le code .

De plus, ce bogue considère la deuxième raison possible qui nous a contourné - le manque de tables InnoDB dans la table système INNODB_SYS_TABLESPACES, si elles, tables, ont été créées dans la version 5.1. Pour éviter les problèmes lors de la mise à niveau, vous pouvez utiliser le script SQL joint .

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

Malheureusement, sur une grande base de données vraiment fonctionnelle, elle ne fonctionnera pas uniquement pour prendre et exécuter l'omniprésente 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 était le suivant:

  1. Optimisez toutes les tables.
  2. Effectuez une mise à niveau de la base 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 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

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 une nouvelle. Dans notre cas, un test a montré que la mise à jour de toutes les tables prendrait environ une journée, mais la copie des données causait trop de charge sur les disques.

Pour éviter cela, lors de la production, nous avons ajouté un argument --sleepavec une valeur de 10 à la commande - ce paramètre contrôle la durée de l'attente après le transfert d'un paquet de données vers une nouvelle table. De cette façon, vous pouvez réduire la charge si une application réellement en cours d'exécution demande du 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 fonctionnait très étrangement: périodiquement, des baisses de connexion commençaient . Voici à quoi cela ressemblait dans la surveillance:



Le graphique en dents de scie est visible dans la capture d'écran, car une partie des threads du serveur MySQL tombait 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. Lors du traitement des erreurs, nous avons trouvé dans les fichiers de stratégie de l'apparmeur «orphelins» du système :

# 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é formés lors de la mise à niveau vers MySQL 5.7 il y a quelques années et appartiennent au package distant. La suppression de 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

finalement


N'importe quelle 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, dans tous les plans de mise à jour, notre équipe inclut également le nettoyage obligatoire des fichiers supplémentaires qui pourraient apparaître à la suite d'actions récentes.

Et avec ce travail graphique pas si professionnel, je voudrais remercier Percona pour ses excellents produits!



PS


Lisez aussi dans notre blog:


All Articles