Expérience pratique de mise à niveau de MySQL 5.7 vers la version 8.0

image

Nous avons récemment mis à niveau nos serveurs de MySQL 5.7 vers 8.0.

Laissons en dehors de la portée de cet article pourquoi et quels nouveaux petits pains sont apparus dans MySQL 8.0, mais à la place, nous parlerons des difficultés rencontrées pendant le processus de mise à niveau.

Tout d'abord, avant la mise à jour, il convient de consulter la liste des modifications et de corriger votre fichier de configuration.

Au minimum, les options suivantes ont été supprimées:
innodb_file_format, innodb_file_format_check, innodb_file_format_max, innodb_large_prefix
query_cache_limit, query_cache_min_res_unit, query_cache_size, query_cache_type, query_cache_wlock_invalidate.

Dans le paramètre sql_mode, en particulier, NO_AUTO_CREATE_USER a été supprimé - ce qui est particulièrement important, car dans MySQL 5.7, il était activé par défaut.

Percona a des instructions pour la mise à niveau sur place. Et dans le cas général, vous pouvez le suivre, cependant, nous avons réussi à mettre à jour un seul cluster de cette manière; pour le reste, une tentative de mise à jour a échoué avec une erreur similaire:

2019-06-22T05:04:18.510888Z 1 [ERROR] [MY-011014] [Server] Found partially upgraded DD. Aborting upgrade and deleting all DD tables. Start the upgrade process again. 2019-06-22T05:04:23.115018Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed. 2019-06-22T05:04:23.115655Z 0 [ERROR] [MY-010119] [Server] Aborting 

Par conséquent, nous avons mis à jour les clusters restants en générant une nouvelle instance vide et en restaurant le vidage de la base de données à partir de la version précédente.

Pour ce faire, tout d'abord, vous avez besoin d'un vidage de base de données. Et ici, le danger n ° 1 vous attend - une décharge faite de manière standard:

 mysqldump -u root -p --hex-blob --default-character-set=utf8mb4 --all-databases --triggers --routines --events > dump.sql 

il ne récupère pas en donnant une erreur:

 ERROR 3554 (HY000) at line 15915: Access to system table 'mysql.innodb_index_stats' is rejected. 

La description se trouve dans le bugtracker MySQL (avec le statut Not a bug :), il y a aussi des conseils sur la façon de vider afin qu'il puisse être restauré:

 mysqldump -u root -p --hex-blob --default-character-set=utf8mb4 --all-databases --triggers --routines --events --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats > dump.sql 

Mais en essayant d'utiliser un tel vidage, s'il y avait des déclencheurs (et nous les avions), le danger # 2 pouvait être attendu, sous la forme d'une telle erreur:

 ERROR 1231 (42000) at line 54: Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER' 

La raison en est que MySQL utilise sql_mode pour les déclencheurs, à savoir: MySQL enregistre la valeur sql_mode pour le déclencheur au moment de sa création et l'exécute toujours avec cette valeur. Et enregistre en conséquence cette valeur dans un vidage.

Description de l'aide pour cela:
dev.mysql.com/doc/refman/8.0/en/create-trigger.html
MySQL stocke le paramètre de variable système sql_mode en vigueur lorsqu'un déclencheur est créé et exécute toujours le corps du déclencheur avec ce paramètre en vigueur, quel que soit le mode SQL du serveur actuel lorsque le déclencheur commence à s'exécuter.

On fait quoi? Nous venons de couper NO_AUTO_CREATE_USER de la décharge terminée. Commande similaire:

 sed "s/50003 SET sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER/50003 SET sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO/g" dump.sql > dump2.sql 

Après cela, le vidage est correctement restauré, mais le danger # 3 nous attend (la vérité tout à fait attendue) - les tables système sont restaurées à l'état de la version 5.7 et nous avons les erreurs suivantes dans les journaux:

 [ERROR] [MY-013143] [Server] Column count of mysql.user is wrong. Expected 51, found 45. The table is probably corrupted 

D'après l'expérience des versions précédentes, cela est traité en exécutant mysql_upgrade - mais depuis la version 8.0.16 - cela ne fonctionne pas, car mysql_upgrade est déclaré obsolète et ne fait rien.

Maintenant, pour provoquer la mise à jour des tables système, vous devez démarrer MySQL avec l'option upgrade = FORCE .

Sur ubuntu frais, cela peut être fait comme suit:

 systemctl set-environment MYSQLD_OPTS="--upgrade=FORCE" 

Redémarrez ensuite MySQL. Eh bien, après une mise à jour réussie, supprimez-la:

 systemctl unset-environment MYSQLD_OPTS 

Source: https://habr.com/ru/post/fr476852/


All Articles