logo piwik

Réseau - Web - GNU/Linux

2014 14 août

Horodatage des sauvegardes de dump de base de donnée

Rédigé par Marc GUILLAUME | Aucun commentaire

Avec MySQL comme avec les autres SGBDr, la façon la plus portable de sauvegarder ses données est d'en extraire des fichiers sql susceptibles de servir à reconstruire la base et y replacer ses données ce qui s'appelle en anglais un « dump ».

MySQL propose un script du nom de mysqldump qui fait ça très bien. Il produit des fichiers texte qui contiennent des instructions sql. Ces fichiers se compressent très bien, et comme les bases sont souvent grandes, les utilitaires comme gzip sont très utiles pour gagner de l'espace disque.

Le problème commence lorsqu'on envisage des sauvegardes incrémentales. Avec les utilitaires comme rsnapshot qui utilise rsync et les liens en dur, seuls les fichiers modifiés depuis la dernière sauvegarde sont sauvegardés. On économise ainsi de l'espace disque et de la bande passante. Mais les fichiers de dump sont à chaque fois nouveaux, car même si leur contenu n'a pas changé, le fichier lui est nouveau. Du coup rsync le télécharge. Et si vous faites un dump des bases de votres serveur MySQL toutes les quatre heures vous allez télécharger six fois par jour la même chose si vos bases reçoivent rarement des modifications.

Il faut donc trouver un moyen de tester si le nouveau dump est différent de l'ancien et si ce n'est pas le cas conserver l'ancien. Ainsi rsync ne le retéléchargera pas inutilement. Il faut donc au cours du processus de création des dumps pouvoir tester si le contenu du nouveau fichier de dump est semblable ou différent de l'ancien.

A priori cela semble simple. Mais plusieurs éléments viennent perturber l'affaire. Le premier c'est que mysqldump par défaut rajoute en fin de fichier la date et l'heure de création. Donc évidemment deux dumps de la même base réalisés à quelques minutes d'intervalle vont donner des fichiers différents puisque contenant des horodatages différents (ce que l'on peut constater avec cmp, diff ou en calculant une somme md5 avec md5sum). Le second est que la compression avec gzip par défaut entre elle aussi un horodatage dans le fichier comprimé. Ce qui fait que si vous réaliser deux archives du même fichier avec gzip, elles vont avoir un octet de différence (justement l'horodatage, ce que l'on peut aussi voir avec cmp, diff ou md5sum).

Comme toujours la lecture de la page de man permet de trouver les solutions. Pour le premier problème man mysqldump dit :

Option --skip-dump-date
However, the date causes dump files taken at different times to appear to be different, even if the data are otherwise identical. --dump-date and --skip-dump-date control whether the date is added to the comment. The default is --dump-date (include the date in the comment). --skip-dump-date suppresses date printing. This option was added in MySQL 5.1.23.

Donc l'option --skip-dump-date est la solution à notre problème, qui supprime l'impression de la date qui semble rendre différents deux fichiers dont les données sql sont identiques. Si vous avez MySQL dans une version supérieure ou égale à MySQL 5.1.23 vous pouvez l'utiliser. C'est le cas sur Debian Wheezy.

Pour le second problème, la page man gzip donne elle aussi la solution :

Option -n --no-name
When compressing, do not save the original file name and time stamp by default. (The original name is always saved if the name had to be truncated.) When decompressing, do  not restore  the  original  file name if present (remove only the gzip suffix from the compressed file name) and do not restore the original time stamp if present (copy it from the compressed file). This option is the default when decompressing.

L'option -n évite que le timestamp soit stocké dans l'archive, rendant ainsi toutes ses versions identiques. On arrive donc à un script de sauvegarde au cours duquel on pourra tester par exemple avec cmp les deux fichiers new-dump.gz et dump.gz

cmp new-dump.gz dump.gz >/dev/null

qui renverra 0 si les fichiers sont identiques ou 1 s'il présentent une différence. Un script de sauvegarde possible utilisant ces options serait donc le suivant (ce script a pour point de départ le script de sauvegarde que j'avais présenté dans un précédent article) :

#!/bin/bash -
# 2014-08-14 Marc Guillaume 
VERSION="0.0.3"

###~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Script de sauvegarde des bases d'un serveur MySQL. Les sauvegardes se font en archives gzipées,
# une par base avec un nom de style mysql_nombase.sql.bz dans un répertoire public, de manière à pouvoir
# les relever avec une sauvegarde rsnapshot
# en ajoutant l'option -s on obtient alors un répertoire du nom de l'horodatage contenant les sauvegardes
# dont le nom est aussi préfixé de l'horodatage pour une éventuelle sauvegarde incrémentale.
###~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# fonction pour le log
function log()
   echo $1 | logger -p local0.notice -t MSQBK;
}


# On indique dans quel répertoire vont se trouver les sauvegardes
BACKUP_DIR="/opt/backupsMySQL/"

Usage(){
  echo""
  echo"$0 version ${VERSION} Sauvegarde des bases d'un serveur MySQL"
  echo"+"
  echo"++ Usage ; "$0"[- [-"
  echo"+"
  echo"+ + [- On crée un sous-répertoire nommé par un horodatage, chaque fichier de base étant lui aussi préfixé de cet horodatge"
  echo"+ + [- affiche la présente aide"
  echo"+"
}

# Cas particulier de l'option -h: doit être seule et les paramètres vides
if [ "$1"=-h ]; then Usage; exit 2; fi

if [ "$1"=-s ]; then
  # On crée un timestamp pour l'horodatage des répertoires et fichiers (année-jour-mois-heure-minute)
  # ce qui permet d'envisager des sauvegardes horaires si besoin est.
  TIMESTAMP=$(date +"%Y%m%d%H%M")
  BACKUPPATH="${BACKUP_DIR}${TIMESTAMP}/"
  # On crée le répertoire de la sauvegarde portant comme nom l'horodatage
  $(mkdir -p ${BACKUPPATH})
else
  BACKUPPATH=${BACKUP_DIR}"public/"
  TIMESTAMP=''
fi

umask 007

# On donne une priorité moyenne au processus
renice 10 $$ > /dev/null

# On lance le dump en parcourant la liste des bases donnée par la commande SHOW DATABASES
# Sur Debian Squeeze il ne semble pas qu'on aie besoin d'ignorer la table mysql.event mais
# on peut laisser l'option sauf si il apparaît une erreur (à voir avec les nouvelles versions de MySQL)
# on zip les sauvegardes. Pour pouvoir les comparer aux anciennes on utilise l'option --skip-dump-date
# pour ne pas avoir d'horodatage interne au fichier de dump (voir man mysqldump) et l'option -n de gzip
# qui elle aussi supprime l'horodatage. Ainsi on peut faire un simple cmp sur les fichiers binaires.
for db in $(mysql --batch --skip-column-names --execute="SHOW DATABASES"|grep -v _schema)
do
if $(/usr/bin/nice /usr/bin/mysqldump --events --ignore-table=mysql.event --single-transaction --skip-dump-date --quick --extended-insert ${db} | gzip -n > ${BACKUPPATH}${TIMESTAMP}new-mysql_${db}.sql.gz); then
if [ -f${BACKUPPATH}${TIMESTAMP}mysql_${db}.sql.gz ]; then
# si il existe une sauvegarde on regarde si le fichier a changé
if [ $(cmp${BACKUPPATH}${TIMESTAMP}new-mysql_${db}.sql.gz ${BACKUPPATH}${TIMESTAMP}mysql_${db}.sql.gz) >/dev/null ]; then
# Ils sont les mêmes on efface donc le nouveau
rm -f ${BACKUPPATH}${TIMESTAMP}new-mysql_${db}.sql.gz;
$(log "Le fichier "${TIMESTAMP}mysql_${db}.sql.gz" n'a pas changé.");
else
# il a changé, on remplace l'ancien fichier
mv ${BACKUPPATH}${TIMESTAMP}new-mysql_${db}.sql.gz ${BACKUPPATH}${TIMESTAMP}mysql_${db}.sql.gz;
$(log "Le fichier "${TIMESTAMP}mysql_${db}.sql.gz" est dans une nouvelle version.");
fi
else
# si le fichier d'un précédent backup n'existe pas on renomme le nouveau fichier pour le créer
mv ${BACKUPPATH}/${TIMESTAMP}new-mysql_${db}.sql.gz ${BACKUPPATH}/${TIMESTAMP}mysql_${db}.sql.gz;
$(log "Le fichier "${TIMESTAMP}mysql_${db}.sql.gz" n'existait pas et a été créé.");
fi
else
exit 1;
fi
done

# Puis on on redonne la sauvegarde à l'utilisateur et au groupe mysql:mysql pour que
# dans une sauvegarde rsync on puisse plus facilement restaurer les bases.
$(chown -R mysql\:${BACKUPPATH})

Écrire un commentaire

Quelle est la deuxième lettre du mot hkkl ?

Fil RSS des commentaires de cet article

À propos

Yakati.info - Réseau - Web - GNU/Linux © 2017

Généré par PluXml en 0.069s  - Administration

Mes coordonnées

Marc Guillaume
contact[at]yakati.info
79150 ÉTUSSON

Crédits

Pour la gestion du contenu

Généré par PluXml, le Blog ou Cms sans base de données

Pour le contenu

Licence Creative Commons
Ce(tte) œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.

Pour le thème

Thème SOLID de blacktie.co adapté pour PluXml