Annexe D. Pouvoir faire des sauvegardes des bases locales ou distantes d'un serveur PostgreSQL du réseau intranet vers une machine-cliente

Table des matières

D.1. Proposition 1: Sauvegarde et restauration rapide par une base
D.1.1. Sauvegarde au format tar du schéma public de la base de données - pg_dump -
D.1.2. Restauration - pg_restore -
D.2. Proposition 2: Sauvegarde pour toutes les bases et toutes les tables sans les définitions des fonctions de PostGIS ou autre- Script général (Côté-client)
D.3. Proposition 2: Restauration
D.3.1. Format sql
D.3.2. Format tar.gz

Mon but ici n'est pas de développer ici le sujet sur la restauration mais de profiter du fait de disposer de MinGW - donc des utilitaires de base de GNU/Linux - pour proposer dans un premier temps d'exploiter les utilitaires de PostgreSQL dans le cas d'un backup/restauration. Puis dans un second temps, de proposer par un shell-script bash, un exemple de script qui permette de sauvegarder vos bases (schémas+tables) aux divers formats: .sql, zippé et en archive compressé .tar.gz . Le deuxième cas exploitera uniquement l'utilitaire pg_dump sans avoir recours à pg_restore.

ATTENTION: La sauvegarde ici proposée ne prend en compte que les tables contenues dans les bases de données: leurs schémas et leurs contenus. Les fonctionnalités de PostGIS (sauf pour les tables geometry_columns et spatial_ref_sys) et autres fonctionnalités faites par l'utilisateur ne sont pas prises en comptes. Nous partons ici du principe que l'utilisateur n'effectue pas ses sauvegardes pour une mise à jour de PostGIS éventuelle! Mais bien dans le souci de continuer à travailler avec la même version de PostGIS. Le cas contraire - celle d'une mise à jour de PostGIS - , veuillez consultez la documentation de PostGIS ou l'annexe Foire Aux Questions.

D.1. Proposition 1: Sauvegarde et restauration rapide par une base

Nous allons ici proposer grâce aux utilitaires effectuer un exemple de sauvegarde/restauration rapide

D.1.1. Sauvegarde au format tar du schéma public de la base de données - pg_dump -

Les données que nous importons dans notre base de données sont stockées dans le schéma public. PostgreSQL propose par défaut 3 formats: sql (texte), .tar (archive), * (compression). Nous allons ici proposé le format de sauvegarde archive. cela se fait en utilisant l'utilitaire en ligne de commande pg_dump. On obtient un descriptif de ce dernier en faisant depuis DOS:

pg_dump --help

Dans mon cas, j'utilise souvent la ligne de commande suivante[8]

pg_dump -n public -vFt -f [base].tar [base]

où les options

  • -n public permet de préciser qu'il ne faut sauvegarder que le schéma public de la base qui contient les données que nous avons importées;

    On pourra dire aussi que si l'on veut avoir une sauvegarde entière de la base on pourra ignorer cette option.
  • -v permet (mode verbeux) permet lors de l'exécution de cette commande d'afficher tous les étapes de la sauvegarde;

  • -Ft permet de préciser que le format de sortie est du .tar;

  • -f précise le nom du fichier de suavegarde.

Par exemple pour sauvegarder la base de données madatabase (cf. "Chapitre PostGIS"), en tapant la ligne de commande ci -dessus on obtient en guise d'output

Figure D.1. Sauvegarde du schéma public de la base madatabase - pg_dump -

Sauvegarde du schéma public de la base madatabase - pg_dump -

D.1.2. Restauration - pg_restore -

Dans le cas pratique d'une restauration ,nous avons recours à l'utilitaire pg_restore. On obtient un descriptif en faisant

pg_restore --help

Dans mon cas, j'utilise souvent la ligne de commande suivante pour une sauvegarde complète

pg_restore -d [base] -civO [base].tar

où les options

  • -c précise d'effacer la table en cours avant de la créer et de la peupler;

  • -i demande de passer outre si la version du serveur PostgreSQL qui charge le contenu de l'archive n'est pas le même que celui du serveur qui a généré l'archive;

  • -O demande de ne pas prendre en compte le nom du super-utilisateur qui a généré l'archive.

  • -v a été abordé dans la sous-section précédente;

Dans le cas particulier, où je ne veux que restaurer par exemple une table, il faut utiliser l'option -t. Ce qui donne la commande suivante:

pg_restore -d [base] -civOt [table] [base].tar

Par exemple dans le cas de la base madatabase pour restaurer la table buildings, on aura l'output suivant

Figure D.2. Restauration de la table buildings dans la base madatabase - pg_restore -

Restauration de la table buildings dans la base madatabase - pg_restore -

Avertissement

A la suite d'une restauration même partielle, si vos données importées sont indexées, il est souvent conseiller de faire un VACUUM ANALYZE.

D.2. Proposition 2: Sauvegarde pour toutes les bases et toutes les tables sans les définitions des fonctions de PostGIS ou autre- Script général (Côté-client)

Le script suivant demande que vous ayez créé un répertoire où se trouvera vos sauvegardes. L'exemple de répertoire choisit ici est /home/$USERNAME qui doit exister avant toute utilisation du script. Le sous-répertoires $USERNAME correspond à celui que MinGW vous aura créé. Au passage merci à Gérald FENOY pour son aide pour ce script... :-). J'utilise ici l'utiltaire pg_dump dont vous pouvez obtenir un descriptif succint d'utilisation en faisant

pg_dump --help

Avertissement

Dans l'intérieur du script, les paramètres de connexion à la machine distante supposent que vous connaissiez les paramètres de connexion à la machine-serveur et que vous soyez logué en tant que super-utilisateur sur toutes les bases distantes.

Le format choisit des sauvegardes dans les trois formats est suffixé avec la date et l'heure de création de la sauvegarde.

path="/home/${USERNAME}/dump"
path_sql="${path}/sql/"
path_zip="${path}/zip/"
path_archive="${path}/archive/"
#
# Les paramètres de la machine-serveur --- LIGNES A MODIFIER !!! ---
#
hote="jenna"
port="5432"
user="davidgis"
password="empr888"
echo ${password} > password.file
echo >> password.file
for i in ${path} ${path_sql} ${path_zip} ${path_archive} 
do
if [ ! -d "$i" ]; then
  mkdir -p "$i"
fi
done


liste_Bases="$(psql -h ${hote} -p ${port} -U ${user} -d template1 -c \
           "SELECT pg_database.datname \
            FROM pg_database, pg_user \
          WHERE pg_database.datdba = pg_user.usesysid \
          and pg_database.datname not \
          like 'template%' order by datname" < password.file \
            | grep -v "\-\-\-" | grep -v "datname" | grep -v "(")"
for r in ${liste_Bases}
do
  base=$r
  for s in ${path_sql} ${path_zip} ${path_archive} 
    do
        if [ ! -d "${s}${base}" ]; then
          mkdir -p "${s}${base}"
        fi
    done
    
  Heure=$(date +%Y-%m-%d-%I-%M-%S)
  echo ${password} > password.file
  echo >> password.file
  filename_sql="${base}-${Heure}.sql"
  filename_zip="${base}-${Heure}.zip"
  filename_archive="${base}-${Heure}.tar.gz"
  echo ===================================================================
  echo Debut extraction de la base ${base}
  echo ===================================================================
  echo "a) Debut Ecriture dans fichier sql:"
liste_Tables="$(psql -h ${hote} -p ${port} -U ${user} -d ${base} -c "select \
tablename from pg_tables where (tablename not like 'pg_%') and \
(tablename not like 'spatial_ref_sys' ) and (tablename not like 'sql%' )\
  order by tablename" < password.file \
 | grep -v "\-\-\-" | grep -v "tablename" | grep -v "(")"

for j in ${liste_Tables}
do 
  echo -n "Exportation de la table $j de la base ${base} en cours...."; 
  pg_dump -h ${hote} -p ${port} -U ${user} -i -c -O -t $j ${base} < password.file >> \
  ${path_sql}${base}/${filename_sql}; 
  echo -e "terminee."; 
done

echo Fin ecriture dans fichier sql

cd ${path_sql}${base}
echo -n "b) Compression au format .zip de la base ${base} en cours..."
echo "." | zip -c -z9 ${filename_zip} ${filename_sql} > /dev/null
mv ${filename_zip} ${path_zip}${base}/${filename_zip}
echo -e "..termine"

echo -n "c) Compression au format .tar.gz de la base ${base} en cours..."
echo "." | tar czvf  ${filename_archive} ${filename_sql} > /dev/null
mv ${filename_archive} ${path_archive}${base}/${filename_archive}
echo -e "..termine"
  echo " "
  echo "  RESUME"
  echo "   Consultez les fichiers:"
  echo "     - SQL : ${path_sql}${base}/${filename_sql}"
  echo "     - ZIP : ${path_zip}${base}/${filename_zip}"
  echo "     - TAR.GZ : ${path_archive}${base}/${filename_archive}"
  echo " "
  echo ===================================================================
  echo Fin extraction de la base ${base}
  echo ===================================================================
done

En exemple d'output par exemple, on obtient

===================================================================
Debut extraction de la base Tlieux
===================================================================
a) Debut Ecriture dans fichier sql:
Exportation de la table communes_lr de la base Tlieux en cours....terminee.
Exportation de la table dep30 de la base Tlieux en cours....terminee.
Exportation de la table departements_lr de la base Tlieux en cours....terminee.
Exportation de la table geometry_columns de la base Tlieux en cours....terminee.
Exportation de la table tlieuxclic de la base Tlieux en cours....terminee.
Exportation de la table tlieuxclictemp de la base Tlieux en cours....terminee.
Exportation de la table tlieuxpersagees de la base Tlieux en cours....terminee.
Exportation de la table tlieuxpersageestemp de la base Tlieux en cours....terminee.
Fin ecriture dans fichier sql
b) Compression au format .zip de la base Tlieux en cours.....termine
c) Compression au format .tar.gz de la base Tlieux en cours.....termine
 
  RESUME
   Consultez les fichiers:
     - SQL : /home/david/dump/sql/Tlieux/Tlieux-2005-07-31-09-59-43.sql
     - ZIP : /home/david/dump/zip/Tlieux/Tlieux-2005-07-31-09-59-43.zip
     - TAR.GZ : /home/david/dump/archive/Tlieux/Tlieux-2005-07-31-09-59-43.tar.gz
 
===================================================================
Fin extraction de la base Tlieux
===================================================================
===================================================================
Debut extraction de la base madatabase
===================================================================
a) Debut Ecriture dans fichier sql:
Exportation de la table buildings de la base madatabase en cours....terminee.
Exportation de la table geometry_columns de la base madatabase en cours....terminee.
Exportation de la table great_roads de la base madatabase en cours....terminee.
Exportation de la table mapserver_desc de la base madatabase en cours....terminee.
Exportation de la table parcs de la base madatabase en cours....terminee.
Exportation de la table personnes de la base madatabase en cours....terminee.
Exportation de la table rivers de la base madatabase en cours....terminee.
Exportation de la table small_roads de la base madatabase en cours....terminee.
Fin ecriture dans fichier sql
b) Compression au format .zip de la base madatabase en cours.....termine
c) Compression au format .tar.gz de la base madatabase en cours.....termine
 
  RESUME
   Consultez les fichiers:
     - SQL : /home/david/dump/sql/madatabase/madatabase-2005-07-31-10-00-17.sql
     - ZIP : /home/david/dump/zip/madatabase/madatabase-2005-07-31-10-00-17.zip
     - TAR.GZ : /home/david/dump/archive/madatabase/madatabase-2005-07-31-10-00-17.tar.gz
 
===================================================================
Fin extraction de la base madatabase
===================================================================

N'hésitez pas à consulter la documentation de PostgreSQL pour obtenir de meilleures informations sur l'utilitaire pg_dump. Pour le support du format zip qui n'est pas livré avec MinGW, vous pouvez le trouver sur le site http://gnuwin32.sourceforge.net.

D.3. Proposition 2: Restauration

La restauration est une intervention à utiliser par exemple dans le cas de corruption de données etc...Nous allons ici envisager la restauration pour les deux formats. Avant tout ,il faut effacer la base, la recréer avec PostGIS et ensuite choisir le format voulu. L'effacement d'une base a lieu en utilisant l'utilitaire dropdb:

dropdb votre_base

Pour la recréer, reportez-vous à la première section du chapitre 4..

D.3.1. Format sql

La restauration a lieu ici en utilisant l'utilitaire psql. Par exemple pour restaurer la base 'madatabase', nous ferons depuis MinGW:

psql -d madatabase -f madatabase-.....sql

où .... désigne le suffixe de date du fichier. A titre d'exemple concret, nous pourrions écrire en tenant compte de la sortie obtenue dans la section précédente:

psql -d madatabase -f /home/david/dump/sql/madatabase/madatabase-2005-07-31-10-00-17.sql

D.3.2. Format tar.gz

La restauration a lieu ici en utilisant l'utilitaire psql et tar. Depuis MinGW,- par exemple pour restaurer la base 'madatabase' - il suffit de faire:

psql -d madatabase -f `tar xvzf madatabase-....tar.gz`

où .... désigne le suffixe de date du fichier. En guise d'illustration, nous obtiendrons l'affichage suivant

#
# On se rend dans le répertoire des archives
#
$ cd /home/david/dump/archive/madatabase/
#
# On lance la décompression à la volée l'archive
# qui nous restitue le fichier au format sql
#
$psql -d madatabase -f `tar xvzf madatabase-2005-07-31-10-00-17.tar.gz` 
SET
SET
SET
SET
psql:madatabase-2005-07-31-10-00-17.sql:11: ERROR:  index "buildings_index_spatial" does not exist
psql:madatabase-2005-07-31-10-00-17.sql:12: ERROR:  relation "public.buildings" does not exist
psql:madatabase-2005-07-31-10-00-17.sql:13: ERROR:  table "buildings" does not exist
SET
SET
CREATE TABLE
ALTER TABLE
CREATE INDEX
.
.
.
SET
SET
SET
SET
psql:madatabase-2005-07-31-10-00-17.sql:442: ERROR:  index "small_roads_index_spatial" does not exist
psql:madatabase-2005-07-31-10-00-17.sql:443: ERROR:  relation "public.small_roads" does not exist
psql:madatabase-2005-07-31-10-00-17.sql:444: ERROR:  table "small_roads" does not exist
SET
SET
CREATE TABLE
ALTER TABLE
CREATE INDEX
#
# Pour des raisons d'encombrements sur le disquen on efface le 
# fichier sql décompressé
#
$rm -f madatabase-2005-07-31-10-00-17.sql

Les notes signalées - les tables ERROR: table "....." does not exist - n'importent pas puisque les tables n'existent plus avant l'import. Si vous relancez les commandes pour une seconde fois -facultatif-!, celles-ci ne seront plus affichées.

Avertissement

A la suite d'une restauration même partielle, si vos données importées sont indexées, il est souvent conseiller de faire un VACUUM ANALYZE.



[8] où le diminutif de l'option -vFt correspond aussi à -v -Ft