Pour effectuer une sauvegarde physique des fichiers de base de donnés, PostgreSQL fournit un programme, pg_basebackup, pouvant fonctionner en local ou à distance.

Combiné avec les fichiers WAL (write ahead log), on pourra effectuer une restauration dans le passé à un point particulier (point in time recovery).

Sauvegarde physique d'une instance ou cluster de base de données PostgreSQL.

Le programme pg_basebackup permet d'effectuer une sauvegarde à chaud des fichiers du cluster vers un format binaire.

Espace de sauvegarde

Dans un premier temps, il est important de déterminer où seront copiés les fichiers (en local ou sur un filesystem NFS, etc). Pour cela on effectue une création d'un répertoire ayant les droits pour postgres (ici on choisi un répertoire local /backup/baseXYZ ):

root:#> mkdir /backup/baseXYZ
root:#> chmod 750 /backup/baseXYZ
root:#> chown postgres:postgres /backup/baseXYZ
Exécution du backup

On exécute pg_basebackup, sous le compte postgres, en indiquant ici un format de sortie tar vers le répertoire préparé :

postgres:#> pg_basebackup -z -Ft -D /backup/baseXYZ

Le résultat génère deux fichier tar.gz, un contenant les fichiers base de données, l'autre les fichiers WAL (contenu du répertoire pg_wal)

postgtres:#> ls -l /backup/baseXYZ/
total 3932
-rw------- 1 postgres postgres 4003031 janv. 11 21:33 base.tar.gz
-rw------- 1 postgres postgres   17066 janv. 11 21:33 pg_wal.tar.gz

Attention ces deux fichiers, dans un environnement de production, doivent être archivé. Le répertoire doit être vidé avant d'effectuer une nouvelle sauvegarde.

Restauration des des fichiers sauvegardés

Dans le cas ou l'on souhaite restaurer les fichiers (problème de base ou suppression de données involontaire), le service du cluster doit être absolument arrêté :

root:#> systemctl stop postgres@12-main

puis le contenu du répertoire des fichiers du cluster supprimé :

root:#> rm -Rf /var/lib/postgresql/12/main/*
root:#> ls -l /var/lib/postgresql/12/main/
total 0

enfin, on restaure les fichiers tar sauvegardés précédemment dans l'ordre suivant, et on redémarre le service du cluster :

root;#> tar xzf /backup/baseXYZ/base.tar.gz -C /var/lib/postgresql/12/main/
root;#> tar xzf /backup/baseXYZ/pg_wal.tar.gz -C /var/lib/postgresql/12/main/pg_wal/ 
root:#> systemctl start postgresql@12-main

Le cluster est de nouveau fonctionnel, mais les données ont été restaurées à la date de la sauvegarde utilisée.

Lorsque que l'on souhaite perdre le moins de données, on doit sauvegarder les fichiers WAL archivés au fil de l'eau.

Sauvegarde physique d'une instance ou cluster de base de données PostgreSQL avec un archivage des fichier WAL.
mise en œuvre de l'archivage des fichiers WAL

On prépare un espace d'archivage des fichiers WAL

root:># mkdir /backup/walXYZ
root:># chmod 750 /backup/walXYZ
root:># chown postgresl:postgresl /backup/walXYZ

Dans le fichier postgresql.conf, on modifie les trois paramètres suivants :

wal_level = replica
archive_mode = on
archive_command = 'test ! -f /backup/walXYZ/%f && cp %p /backup/walXYZ/%f'

La commande utilisée avec le paramètre archive_command est une commande basique qui vérifie la non existence de l'archive dans la destination, et si ok, copie ce fichier dans le répertoire cible, ici /backup/walXYZ/. Bien sur la commande peut être plus sophistiqué, mais elle doit retourner la valeur ok (0) pour valider la bonne exécution de la commande.

Après les modifications effectuées, on redémarre le service cluster

root:#> systemctl stop postgres@12-main
Vérification du bon fonctionnement de l'archivage
postgres:#> psql -c "select pg_switch_wal()"
 pg_switch_wal
---------------
 0/D0001D8
(1 row)

postgres:#> ls /backup/walXYZ/
00000001000000000000000D

postgres:#> ls /var/lib/postgresql/12/main/pg_wal/
00000001000000000000000D  00000001000000000000000E  archive_status

postgres:#> ls /var/lib/postgresql/12/main/pg_wal/archive_status/
00000001000000000000000D.done

Le répertoire cible contient bien le nouveau WAL, (...OD), fichier bien sur toujours présent dans le répertoirte pg_wal, et on à un fichier de nom identique avec une extension .done dans le répertoire archive_status pour confirmer la fin correcte de l'archivage. Dans un environnement de production il sera necessaire de purger les fichier WAL bine archivés.

Backup physique

Comme le backup précédemment effectué avec pg_basebackup, on effectue un backup de façon régulière (par exemple 1 fois par jour), mais sans les fichiers WAL (-X none) (voir l'aide avec pg_basebackup --help ) :

postgres:#> pg_basebackup -X none -z -Ft -D /backup/baseXYZ
NOTICE:  all required WAL segments have been archived
postgres:#>  ls -l /backup/baseXYZ
total 3912
-rw------- 1 postgres postgres 4003265 janv. 11 22:54 base.tar.gz
Restauration des données avec un point de restauration particulier

Tout d'abord,on arrête le service du cluster.

Si la place nécessaire est disponible, copier le répertoire complet de données de l'instance et tous les tablespaces dans un emplacement temporaire en prévision d'un éventuel besoin ultérieur. S'il n'y a pas assez de place disponible, il faut au minimum copier le contenu du sous-répertoire pg_wal du répertoire des données de l'instance car il peut contenir des journaux qui n'ont pas été archivés avant l'arrêt du serveur.

On peut alors supprimer les données avant restauration

root:#> systemctl stop postgres@12-main
root:#> 
root:#> rm -Rf /var/lib/postgresql/12/main/*
root:#> ls -l /var/lib/postgresql/12/main/
total 0

Puis on restaure les fichiers sauvegardés précédemment par pg_basebackup :

root:#> tar xzf /backup/baseXYZ/base.tar.gz -C /var/lib/postgresql/12/main/

Puis pour exécuter la restauration, en totalité ou au point d'arrêt spécifié dans le paramètre de cible (target), on modifie le fichier postgresql.conf en vérifiant la commande de restauration des archives nécessaires et en indiquant, éventuellement, une cible d'arrêt de récupération. Pour passer en mode recovery, il est nécessaire de créer un fichier recovery.signal dans le répertoire des données du cluster avant le démarrage du cluster de données.

Il peut être judicieux de modifier temporairement le fichier pg_hba.conf pour empêcher les utilisateurs ordinaires de se connecter tant qu'il n'est pas certain que la récupération a réussi.

Par exemple, une commande de restauration des archives, et une cible spécifiant une heure précise :

restore_command = 'cp /backup/walXYZ/%f %p'
recovery_target_time = '2021-12-10 12:00:00 UTC'

On démarre de service.

root:#> systemctl start postgresql@12-main

Le serveur se trouve alors en mode récupération et commence la lecture des fichiers WAL archivés dont il a besoin. Si la récupération se termine sur une erreur externe (commande erronée, fichier manquant), le serveur peut tout simplement être relancé après correction du problème. Il continue alors la récupération.

À la fin du processus de récupération, le serveur supprime le fichier recovery.signal (pour éviter de retourner accidentellement en mode de récupération), puis passe en mode de fonctionnement normal.

Autre cibles de restauration et options

Par défaut, la restauration continuera jusqu'à la fin des WAL. Les paramètres suivants peuvent être utilisés pour indiquer un point d'arrêt. Au moins un des paramètres parmi recovery_target, recovery_target_name et recovery_target_time peut être utilisé. Si plus d'un paramètre est indiqué dans le fichier de configuration, une erreur sera renvoyée.

recovery_target = 'immediate'
Ce paramètre indique que la restauration doit s'arrêter dès qu'un point de cohérence est atteint, autrement dit le plus tôt possible. Lors de la restauration d'une sauvegarde, cela signifie le moment où la sauvegarde s'est terminée.
recovery_target_name (string)
Ce paramètre indique le point de restauration nommé, créé précédemment avec la fonction pg_create_restore_point(<UNIQUE_NAME>) où la restauration doit s'arrêter.
recovery_target_time (timestamp)
Ce paramètre indique jusqu'à quel date et heure la restauration doit s'arrêter. Le point d'arrêt précis est aussi influencé par recovery_target_inclusive.

Les options suivantes peuvent être utilisées :

recovery_target_inclusive (boolean)
Indique s'il faut arrêter juste après la cible de restauration indiquée (on) ou juste avant (off). S'applique quand recovery_target_time spécifié. La valeur par défaut est on.
recovery_target_action (enum)
Indique l'action que le serveur devra prendre une fois la cible de restauration atteinte. La valeur par défaut est pause, ce qui signifie que la restauration sera mise en pause. promote signifie que le processus de restauration finira et que le serveur démarrera pour accepter toute connexion. Enfin, shutdown arrêtera le serveur après avoir atteint la cible de restauration.

Pour tout problème, n'oubliez pas de consulter le fichier de log du cluster.

Bon backup ^^