Praktische Erfahrung mit dem Upgrade von MySQL 5.7 auf Version 8.0

Bild

Wir haben kürzlich unsere Server von MySQL 5.7 auf 8.0 aktualisiert.

Lassen Sie uns den Rahmen dieses Artikels verlassen, warum und welche neuen Buns in MySQL 8.0 erschienen sind. Stattdessen werden wir darüber sprechen, auf welche Schwierigkeiten wir während des Upgrade-Prozesses gestoßen sind.

Erstens, bevor Sie ein Update durchführen, sollten Sie sich die Liste der Änderungen ansehen und Ihre Konfigurationsdatei korrigieren.

Die folgenden Optionen wurden mindestens gelöscht:
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.

Insbesondere im Parameter sql_mode wurde NO_AUTO_CREATE_USER gelöscht - was besonders wichtig ist, weil In MySQL 5.7 war es standardmäßig aktiviert.

Percona verfügt über Anweisungen zum direkten Upgrade. Im Allgemeinen können Sie dem folgen, es ist uns jedoch gelungen, nur einen Cluster auf diese Weise zu aktualisieren, im Übrigen ist ein Versuch, dies zu aktualisieren, mit einem ähnlichen Fehler fehlgeschlagen:

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 

Aus diesem Grund haben wir die verbleibenden Cluster aktualisiert, indem wir eine neue leere Instanz ausgelöst und den Datenbankspeicherauszug aus der vorherigen Version wiederhergestellt haben.

Dazu benötigen Sie zunächst einen Datenbankspeicherauszug. Und hier wartet die Gefahr Nr. 1 - eine Müllkippe, die auf die übliche Weise hergestellt wurde:

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

es wird nicht wiederhergestellt, was zu einem Fehler führt:

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

Die Beschreibung befindet sich im MySQL-Bugtracker (mit dem Status Not a bug :). Es gibt auch Hinweise, wie Sie einen Speicherauszug erstellen, damit er wiederhergestellt werden kann:

 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 

Bei dem Versuch, einen solchen Speicherauszug zu verwenden, war jedoch die Gefahr Nr. 2 in Form eines solchen Fehlers zu erwarten, wenn Trigger darin vorhanden waren (und wir hatten sie):

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

Der Grund dafür ist, dass MySQL sql_mode für Trigger verwendet, und zwar: MySQL speichert den sql_mode-Wert für den Trigger zum Zeitpunkt seiner Erstellung und führt ihn dann immer mit diesem Wert aus. Und speichert dementsprechend diesen Wert in einem Dump.

Hilfebeschreibung dazu:
dev.mysql.com/doc/refman/8.0/en/create-trigger.html
MySQL speichert die Einstellung der Systemvariablen sql_mode, die beim Erstellen eines Triggers wirksam ist, und führt den Trigger-Body immer mit dieser Einstellung aus, unabhängig vom aktuellen SQL-Modus des Servers, wenn der Trigger mit der Ausführung beginnt.

Was machen wir Wir haben gerade NO_AUTO_CREATE_USER vom fertigen Dump abgeschnitten. Ähnliches Kommando:

 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 

Danach wird der Speicherauszug erfolgreich wiederhergestellt, aber Gefahr 3 wartet auf uns (die durchaus erwartete Wahrheit). Die Systemtabellen wurden ab Version 5.7 auf den Stand zurückgesetzt, und in den Protokollen sind die folgenden Fehler aufgetreten:

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

Aus Erfahrung mit früheren Versionen wird dies durch Ausführen von mysql_upgrade behoben - aber seit Version 8.0.16 funktioniert dies nicht, weil mysql_upgrade wird für veraltet erklärt und unternimmt nichts.

Damit die Systemtabellen aktualisiert werden, müssen Sie MySQL mit der Option upgrade = FORCE starten.

Auf frischem Ubuntu kann dies folgendermaßen erfolgen:

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

Starten Sie dann MySQL neu. Nun, nach einem erfolgreichen Update löschen Sie es:

 systemctl unset-environment MYSQLD_OPTS 

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


All Articles