Déplacer une base, c'est un export et un import. Ce qui fait échouer l'opération, c'est ce que l'export ne contient pas - et le découvrir une fois le site déjà pointé vers le nouveau serveur.

L'export

mysqldump --single-transaction --quick --routines --triggers --events \
          --default-character-set=utf8mb4 shop | gzip > shop.sql.gz

Le transfert

scp shop.sql.gz newserver:/tmp/
# or stream it directly, with no file in between
mysqldump --single-transaction shop | gzip | ssh newserver 'gunzip | mysql shop'

Créer la cible correctement, avant d'importer

mysql -e "CREATE DATABASE shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
zcat /tmp/shop.sql.gz | mysql shop
Créez d'abord la base avec le bon jeu de caractères. Importer dans une base latin1 donne un schéma qui a l'air juste et abîme l'arabe et les emoji en silence - voyez jeu de caractères et collation.

Les trois choses que l'export n'emporte pas

  • Les utilisateurs et les droits. Ils vivent dans le schéma mysql. Recréez-les - voyez utilisateurs et droits.
  • La configuration du serveur. Buffer pool, max_connections, délais. Reportez les lignes qui vous concernent.
  • Les événements planifiés, sauf si vous avez passé --events, et le planificateur d'événements doit aussi être activé sur le nouveau serveur.
CREATE USER 'shop'@'localhost' IDENTIFIED BY '...';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'shop'@'localhost';
SET GLOBAL event_scheduler = ON;

Vérifier avant de basculer

# same table count, same row counts on the tables that matter
mysql -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='shop'"
mysql shop -e "SELECT COUNT(*) FROM orders; SELECT COUNT(*) FROM customers"
Comparez le nombre de lignes avec l'ancien serveur avant de pointer l'application vers le nouveau. Un import qui échoue à mi-chemin se termine quand même sans se plaindre sur certains chemins, et une demi-base ressemble exactement à une base qui marche - jusqu'à ce que quelqu'un cherche le mois dernier.