Blog

Utilisation de Xtrabackup via innobackupex

Écrit le 12 07 2013 par Kévin MET _

Introduction à Xtrabackup

La sauvegarde à chaud de bases de données MySQL via Xtrabackup est vraiment très pratique. En effet, cela permet de ne pas locker les tables lors du dump (sauf pour les tables en MyISAM). Ce soft est écrit et maintenu par Percona et est compatible avec MariaDB, Mysql Community et Percona MySQL. Il permet de faire des sauvegardes incrémentielles, de créer plus facilement un slave ou d'ajouter rapidement un nouveau node dans un cluster Galera. Cependant, c'est un peu plus compliqué à utiliser que ce bon vieux mysqldump. Le plus simple pour mettre en œuvre ce type de sauvegarde est d'utilisé le script perl innobackupex qui est fourni dans le paquet Xtrabackup et c'est ce que nous allons voir dans ce tutoriel.

Installation

Pour commencer, on va faire une installation sur Debian via les dépôts Percona. C'est la méthode la plus simple et la plus Debian friendly à mon sens. Il faut simplement ajouter le dépôt Percona dans notre /etc/apt/sources.list, ajouter la clé GPG et installer le paquet.


# echo -e "deb http://repo.percona.com/apt wheezy main\ndeb-src http://repo.percona.com/apt wheezy main" >> /etc/apt/sources.list
# apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
# apt-get update
# apt-get install xtrabackup

Et voilà, c'est tout pour la partie installation. Maintenant on va voir comment utiliser tout cela.

Utilisation de innobackupex

Durant tout ce tutoriel nous n'allons jamais utiliser Xtrabckup directement mais innobackupex qui est un wrapper en perl pour Xtrabackup (qui lui est écrit en C). Pour commencer il faut un utilisateur avec quelques droits particuliers pour effectuer les sauvegardes. Vous pouvez utiliser le compte root mais il est plus judicieux d'un point de vue sécurité de créer un utilisateur spécialement à cet effet. Le compte root étant uniquement réserver à l'admin avec un vrai humain au commande (car évidemment le but est de scripter les sauvegardes et les lancer toutes les nuits/12h/heures selon vos besoins). Pour créer notre utilisateur backup avec le mot de passe s3cret on procède comme cela :


CREATE USER 'backup'@'localhost' IDENTIFIED BY 's3cret';
GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup'@'localhost';

Fonctionnement de Xtrabackup

La sauvegarde et la restauration de vos bases de données ne s'effectue pas en 2 temps comme avec mysqldump mais en 3 temps :

  • La sauvegarde
  • La préparation
  • La restauration

En effet, Xtrabackup ne fait pas un simple fichier avec les statements comme mysqldump. Il va copier la structure de vos bases (les .frm), il copie les logs innodb dans le fichier xtrabackup_logfile et il copie les données innodb. Ceci est un résumé grossier de ce qu'il se passe mais ça suffit pour comprendre l'étape de préparation. Lors de la préparation les logs seront rejoués et les data seront donc mises à jour. Il ne restera plus qu'à faire un rsync de vos données dans le dossier data de votre serveur MySQL. On peut également utiliser innobackupex pour gérer la restauration.

Sauvegarde et restauration complète de toutes vos bases

Après la théorie on passe à la pratique. On va donc commencer par faire une sauvegarde de toutes les bases.


# innobackupex --user=backup --password=s3cret /root/tmp/

Le script va créer un dossier avec le timestamp dans /root/tmp qui contiendra la sauvegarde. Si tout se déroule bien, vous devez obtenir un message similaire à celui-ci. Sinon c'est que la sauvegarde a échoué.


130711 19:20:49  innobackupex: completed OK!

Pour préparer la sauvegarde on va exécuter les logs avec la commande suivante :


# innobackupex --apply-log /root/tmp/2013-07-11_19-20-18/

Pour être sur que tout s'est bien déroulé, on doit obtenir un joli message comme celui-ci :


130712 17:44:35  innobackupex: completed OK!

Pour faire une restauration, il suffit d'utiliser l'option --copy-back:


# innobackupex --copy-back /root/tmp/2013-07-11_19-20-18/

Et comme pour les autres étapes on doit obtenir un beau innobackupex: completed OK.

Sauvegarde et restauration de certaines bases

La sauvegarde de certaines bases peut se faire uniquement si le serveur MySQL utilise l'option innodb_file_per_table. La sauvegarde se fait quasiment comme pour une sauvegarde de toutes les bases et la réimportation est un peu différente car on ne peut pas utiliser l'option --copy-back. Dans la suite de ce tutoriel, je pars du principe que je souhaite sauvegarder la base dolibarr.

Lors de la sauvegarde on dispose de 3 options pour spécifier les bases et tables que l'on veut sauver :

  • --include : avec laquelle on peut utiliser une expression régulière pour désigner des bases et des tables
  • --tables-file : qui permet de spécifier un fichier dans lequel on liste les tables
  • --databases : qui permet de spécifier une liste de base mais qui ne fonctionne que avec MyISAM

Étant donné, le caractère contraignant de l'option --databases on va utiliser --tables-file dans cet exemple. On commence par donner les droits suffisants à l'utilisateur backup pour lister les tables d'une bases.


GRANT SELECT ON mysql.innodb_table_stats TO 'backup'@'localhost' IDENTIFIED BY 's3cret';

Ensuite on va créer un fichier contenant la liste des tables que l'on veut sauvegarder. Pour cela on s'appuie sur le nom de la base que l'on veut sauver et on va mettre dans un fichier texte cette liste.


mysql -u backup -ps3cret -r -e "SELECT CONCAT(database_name, '.', table_name) FROM mysql.innodb_table_stats WHERE database_name='dolibarr';" > list.txt

Certaines versions de MySQL vont poser problèmes et ajouter des lignes dans le fichier list.txt. Dans ce cas, il suffit d'ajouter un simple awk '{ print $2}' avant d’envoyer la liste des tables dans le fichier texte.


mysql -u backup -ps3cret -r -e "SELECT CONCAT(database_name, '.', table_name) FROM mysql.innodb_table_stats WHERE database_name='dolibarr';" | awk '{ print $2}' > list.txt

On va pouvoir effectuer notre sauvegarde en utilisant ce fichier :


# innobackupex --user=backup --password=s3cret --tables-file=/root/list.txt /root/tmp/

Ceci va comme précédemment créer un dossier avec le timestamp contenant les fichiers sauvegardés.

Le problème de cette méthode, c'est que la structure des tables n'est pas sauvée (sauf dans les fichiers .frm) mais comme c'est un peu compliqué à restaurer on va plutôt passer par mysqldump pour exporter le schéma des tables. Pour cela, on utilise l'option --no-data de mysqldump.


mysqldump -u root -p --no-data dolibarr > dolibarr_schema.sql

Il nous faut maintenant préparer la sauvegarde en utilisant l'option --export qui va permettre de créer un fichier .exp contenant l'export que l'on pourra injecter dans notre base de données.


# innobackupex --apply-log --export /root/tmp/2013-07-16_11-23-38/

Vous allez rencontrez de nombreux WARNINGS tels que celui-ci :


InnoDB: Table test/llx_notify in the InnoDB data dictionary has tablespace id 633, but tablespace with that id or name does not exist. Have you deleted or moved .ibd files? This may also be a table created with CREATE TEMPORARY TABLE whose .ibd and .frm files MySQL automatically removed, but the table still exists in the InnoDB internal data dictionary.
InnoDB: It will be removed from the data dictionary.
InnoDB: Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting-datadict.html
InnoDB: for how to resolve the issue.

Cela n'est pas important et vous ne devez pas en tenir compte tant que vous obtenez le message innobackupex: completed OK. Cela est du au fait qu'InnoDB enregistre son data dictionary dans les fichiers tablespace (.ibd) en plus des fichiers .frm. Logiquement les fichiers d'exports .exp sont créés et il en existe un par table.

On peut maintenant passer à la restauration de la base. Pour cela on va commencer par réimporter le schéma de notre base.


# mysql -u root -p dolibarr < dolibarr_schema.sql

On va ensuite se connecter en CLI à MySQL et locker les tables et supprimer les fichiers de tablespace des tables.


mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10329
Server version: 5.6.12 MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> LOCK TABLES llx_accounting_system WRITE;
Query OK, 0 rows affected (0.00 sec)

mysql> set FOREIGN_KEY_CHECKS=0;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE llx_accounting_system DISCARD TABLESPACE;
Query OK, 0 rows affected (0.04 sec)

Une fois que l'on a fait cela pour chaque tables de notre base (on peut scripter avec le fichier list.txt pour gagner du temps) on va devoir arrêter le serveur MySQL et copier les fichiers .ibd et .exp dans le dossier data.


/etc/init.d/mysql stop

# cp /root/tmp/2013-07-16_11-23-38/dolibarr/llx_accounting_system.exp /root/tmp/2013-07-16_11-23-38/dolibarr/llx_accounting_system.ibd /var/lib/mysql/data/dolibarr/

On peut aussi copier tous les fichiers d'un coup si on doit restaurer toutes les tables


# cp /root/tmp/2013-07-16_11-23-38/dolibarr/*.exp /root/tmp/2013-07-16_11-23-38/dolibarr/*.ibd /var/lib/mysql/data/dolibarr/

Il ne reste plus qu'a importer ce nouveau tablespace par table.


mysql> ALTER TABLE llx_accounting_system IMPORT TABLESPACE;
Query OK, 0 rows affected (0.04 sec)

mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)

On peut de nouveau s'appuyer sur list.txt pour scripter

♥ Partage sur tes réseaux sociaux ♥
Kévin MET
Kévin MET

Auteur de ce blog et gérant de la société MNT-TECH, je publie sur ce blog lorsque le temps me le permet et lorsqu'un sujet qui me parait intéressant n'a pas encore été abordé en français. Toutes les informations techniques présentes sur cette page peuvent être réutilisées moyennant le fait de citer la source.