le 4 Octobre 2018
Il existe deux manières possibles pour migrer un serveur MySQL 5.7 vers 8.0 : la migration INPLACE et la migration LOGICAL.
La migration INPLACE est généralement préférable, cela consiste à installer MySQL 5.7, importer les données puis upgrader le tout. Cette méthode est bien documentée et vous n'aurez aucun mal à trouver des procédures sur internet.
La méthode LOGICAL consiste, elle, à installer directement MySQL 8.0 puis importer les données préalablement extraites sur un MySQL 5.7 (par mysqldump par exemple). Cette méthode est plus complexe car vous devez vous assurer que le dump en question est compatible. Si pour une raison quelconque vous ne souhaitez pas installer MySQL 5.7 et vous n'avez pas le temps de contrôler votre dump alors cette fiche 'quick & dirty' vous aider à dupliquer rapidement vos données vers MySQL 8.0.
Notez que cette procédure a été pensée pour une installation vierge de MySQL 8.0 pour configurer une réplication Master-Slave avec un MySQL 5.7, l'idée étant de migrer en douceur sans impacter la production. Nous vous déconseillons donc fortement d'utiliser une base MySQL 8.0 déjà active, ou alors réalisez une sauvegarde complète avant !
Enfin, cette procédure ne fonctionnera pas pour des versions antérieures de MySQL (5.5, 5.6 etc...), vous devrez impérativement upgrader en version 5.7 avant.
Sur le serveur source, commençons par exporter toutes les bases sans les données, afin de valider plus rapidement l'import :
mysqldump -u root --all-databases --no-data --single-transaction --master-data=1 --triggers --routines --events --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats | gzip -9 > /tmp/dump-nodata.sql.gz
Copiez le fichier dump-nodata.sql.gz
sur le serveur destination et tentez de l'importer sur le serveur MySQL 8.0 :
gunzip /tmp/dump-nodata.sql.gz mysql < /tmp/dump-nodata.sql
ERROR 3554 (HY000) at line 8089: Access to system table 'mysql.innodb_index_stats' is rejected.
--ignore-table
à votre export pour la table concernée et recommencez l'opération (--ignore-table=mysql.innodb_index_stats
pour notre exemple )--ignore-table
que vous aurez ajouté : mysqldump -u root --all-databases --single-transaction --master-data=1 --triggers --routines --events --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats | gzip -9 > /tmp/dump.sql.gz
Copiez le fichier dump.sql.gz
sur le serveur destination et tentez de l'importer sur le serveur MySQL 8.0 :
gunzip /tmp/dump.sql.gz mysql < /tmp/dump.sql
Les données importées sont malheureusement incompatibles avec MySQL 8.0, nous devons donc les migrer. D'autre part, étant donné que nous avons importé la table mysql.user
, les mots de passes ont pu changer et l'accès n'est sans doute plus possible.
Nous allons donc arrêter MySQL et le redémarrer sans contrôle d'accès :
systemctl stop mysqld /sbin/mysqld --skip-grant-tables &
mysql_upgrade --force
mysql_check.sh full
killall -SIGQUIT mysqld systemctl start mysqld
Assurez vous en premier lieu que vous pouvez vous connecter à la base (attention, les mots de passes sont ceux du serveur source !).
Ensuite, voici un petit script qui vous permetta de contrôler le nombre de ligne de chaque table, exécutez le sur les serveurs source et destination, le résultat doit être identique :
for db in $( mysql -Ne 'show databases' | grep -v 'information_schema\|performance_schema\|mysql\|sys' ) ; do for table in $( mysql $db -Ne "show tables" ); do count=$( mysql -Ne "select count(*) from \`${db}\`.\`${table}\`" ) echo -e "${db}.${table}\t${count}" done done