

   PostgreSQL maintient en permanence des journaux
   de transactions(Write Ahead Log ou
   WAL) dans le sous-répertoire
   pg_wal/ du répertoire de données de l'instance. Ces
   journaux enregistrent chaque modification effectuée sur les fichiers de
   données des bases. Ils existent principalement pour se prémunir des suites
   d'un arrêt brutal : si le système s'arrête brutalement, la base de
   données peut être restaurée dans un état cohérent en
   « rejouant » les entrées des journaux enregistrées depuis le
   dernier checkpoint. Néanmoins, l'existence de ces journaux rend possible
   l'utilisation d'une troisième stratégie pour la sauvegarde des bases de
   données : la combinaison d'une sauvegarde de niveau système de
   fichiers avec la sauvegarde des journaux de transactions. Si la
   restauration est nécessaire, la sauvegarde des fichiers est restaurée,
   puis les journaux de transactions sauvegardés sont rejoués pour amener la
   sauvegarde jusqu'à la date actuelle. Cette approche est plus complexe à
   administrer que toutes les autres approches mais elle apporte des
   bénéfices importants :
   
Il n'est pas nécessaire de disposer d'une sauvegarde des fichiers parfaitement cohérente comme point de départ. Toute incohérence dans la sauvegarde est corrigée par la ré-exécution des journaux (ceci n'est pas significativement différent de ce qu'il se passe lors d'un rejeu après un arrêt brutal). La fonctionnalité d'image du système de fichiers n'est alors pas nécessaire, tar ou tout autre outil d'archivage est suffisant.
Puisqu'une longue séquence de journaux de transactions peut être assemblée pour être rejoués, une sauvegarde continue est obtenue en continuant simplement à archiver les journaux de transactions. C'est particulièrement intéressant pour les grosses bases de données dont une sauvegarde complète fréquente est difficilement réalisable.
Les entrées des journaux de transactions ne doivent pas obligatoirement être rejouées intégralement. La ré-exécution peut être stoppée en tout point, tout en garantissant une image cohérente de la base de données telle qu'elle était à ce moment-là. Ainsi, cette technique autorise la restauration d'un instantané (PITR) : il est possible de restaurer l'état de la base de données telle qu'elle était en tout point dans le temps depuis la dernière sauvegarde de base.
Si la série de journaux de transactions est fournie en continu à une autre machine chargée avec le même fichier de sauvegarde de base, on obtient un système « de reprise intermédiaire » (warm standby) : à tout moment, la deuxième machine peut être montée et disposer d'une copie quasi-complète de la base de données.
pg_dump et pg_dumpall ne font pas de sauvegardes au niveau système de fichiers. Ce type de sauvegarde est qualifié de logique et ne contient pas suffisamment d'informations pour permettre le rejeu des journaux de transactions.
Tout comme la technique de sauvegarde standard du système de fichiers, cette méthode ne supporte que la restauration d'une instance de bases de données complet, pas d'un sous-ensemble. De plus, un espace d'archivage important est requis : la sauvegarde de la base peut être volumineuse et un système très utilisé engendre un trafic de journaux de transactions à archiver de plusieurs Mo. Malgré tout, c'est la technique de sauvegarde préférée dans de nombreuses situations où une haute fiabilité est requise.
Une restauration fructueuse à partir de l'archivage continu (aussi appelé « sauvegarde à chaud » par certains vendeurs de SGBD) nécessite une séquence ininterrompue de journaux de transactions archivés qui s'étend au moins jusqu'au point de départ de la sauvegarde. Pour commencer, il faut configurer et tester la procédure d'archivage des journaux de transactions avant d'effectuer la première sauvegarde de base. C'est pourquoi la suite du document commence par présenter les mécanismes d'archivage des journaux de transactions.
Au sens abstrait, un système PostgreSQL fonctionnel produit une séquence infinie d'enregistrements de journaux de transactions. Le système divise physiquement cette séquence en fichiers de segment WAL de 16 Mo chacun (en général, mais cette taille peut être modifiée lors de l'exécution d'initdb). Les fichiers segment reçoivent des noms numériques pour refléter leur position dans la séquence abstraite des journaux de transactions. Lorsque le système n'utilise pas l'archivage des journaux de transactions, il ne crée que quelques fichiers segments, qu'il « recycle » en renommant les fichiers devenus inutiles. Un fichier segment dont le contenu précède le dernier checkpoint est supposé inutile et peut être recyclé.
    Lors de l'archivage des journaux de transactions, le contenu de chaque
    fichier segment doit être capturé dès qu'il est rempli pour sauvegarder les
    données ailleurs avant son recyclage. En fonction de l'application et du
    matériel disponible, « sauvegarder les données ailleurs » peut se
    faire de plusieurs façons : les fichiers segment peuvent être copiés
    dans un répertoire NFS monté sur une autre machine, être écrits sur une
    cartouche (après s'être assuré qu'il existe un moyen d'identifier le nom
    d'origine de chaque fichier) ou être groupés pour gravure sur un CD, ou
    toute autre chose. Pour fournir autant de flexibilité que possible à
    l'administrateur de la base de données,
    PostgreSQL essaie de ne faire aucune supposition
    sur la façon dont l'archivage est réalisé. À la place,
    PostgreSQL permet de préciser une commande shell
    ou une bibliothèque d'archivage à exécuter pour copier le fichier segment
    complet à l'endroit désiré. Cela peut être aussi simple qu'une commande
    shell qui utilise cp ou cela peut appeler une fonction C
    complexe  --  c'est l'utilisateur qui décide.
   
    Pour activer l'archivage des journaux de transaction, configurez le
    paramètre de configuration wal_level à
    replica ou supérieur, archive_mode
    à on, et précisez la commande shell à utiliser dans le
    paramètre de configuration archive_command ou précisez
    la bibliothèque à utiliser dans le paramètre archive_library de la configuration. En fait, ces paramètres
    seront toujours placés dans le fichier postgresql.conf.
   
    Un moyen simple d'archiver est de configurer le paramètre
    archive_library avec une chaîne vide et de spécifier une
    commande shell au niveau du paramètre archive_command.
    Dans cette chaîne, un %p est remplacé par le chemin
    absolu de l'archive alors qu'un %f n'est remplacé que par
    le nom du fichier. (Le nom du chemin est relatif au répertoire de travail du
    serveur, c'est-à-dire le répertoire des données de l'instance.)
    %% est utilisé pour écrire le caractère
    % dans la commande. La commande la plus simple ressemble
    à :
archive_command = 'test ! -f /mnt/serveur/repertoire_archive/%f && cp %p /mnt/serveur/repertoire_archive/%f' # Unix archive_command = 'copy "%p" "C:\\serveur\\repertoire_archive\\%f"' # Windows
    qui copie les segments WAL archivables dans le répertoire
    /mnt/serveur/repertoire_archive. (Ceci est un
    exemple, pas une recommandation, et peut ne pas fonctionner sur toutes
    les plateformes.) Après le remplacement des paramètres
    %p et %f, la commande réellement
    exécutée peut ressembler à :
test ! -f /mnt/serveur/repertoire_archive/00000001000000A900000065 && cp pg_wal/00000001000000A900000065 /mnt/serveur/repertoire_archive/00000001000000A900000065
Une commande similaire est produite pour chaque nouveau fichier à archiver.
La bibliothèque d'archivage est exécutée sous l'identité de l'utilisateur propriétaire du serveur PostgreSQL. La série de journaux de transactions en cours d'archivage contient absolument tout ce qui se trouve dans la base de données, il convient donc de s'assurer que les données archivées sont protégées des autres utilisateurs ; on peut, par exemple, archiver dans un répertoire sur lequel les droits de lecture ne sont positionnés ni pour le groupe ni pour le reste du monde.
Il est important que la commande d'archivage renvoie le statut de sortie zéro si et seulement si elle réussit. En cas de réception d'un code zéro, PostgreSQL supposera que le fichier a été archivé avec succès, et le supprimera ou le recyclera. Néanmoins, un code différent de zéro indique à PostgreSQL que le fichier n'a pas été archivé ; il essaiera de nouveau périodiquement jusqu'à sa réussite.
    Une autre façon d'archiver est d'utiliser un module d'archivage personnalisé
    avec archive_library. Comme de tels modules sont écrits
    en C, créer son propre module nécessite considérablement plus d'effort que
    d'écrire une commande shell. Néanmoins, les modules d'archivage peuvent être
    plus performants que l'archivage via le shell, et ils auront accès à un
    grand nombre de ressources serveurs utiles.  Pour plus d'informations sur
    les modules d'archivage, voir Chapitre 49.
   
    Quand la commande d'archivage est terminée par un signal (autre que le
    signal SIGTERM qui est utilisé comme partie d'un
    arrêt du serveur) ou une erreur par le shell avec un statut de sortie plus
    grand que 125 (tel que « command not found »), ou si la fonction
    d'archivage émet un message ERROR ou
    FATAL, le processus d'archivage annule ou est redémarré
    par le processus postmaster. Dans de tels cas, l'échec n'est pas reporté
    dans pg_stat_archiver.
   
En général, les commande et bibliothèques d'archivage doivent être conçue pour refuser d'écraser tout fichier archive déjà existant. C'est une fonctionnalité de sécurité importante pour préserver l'intégrité de l'archive dans le cas d'une erreur de l'administrateur (comme l'envoi de la sortie de deux serveurs différents dans le même répertoire d'archivage). Il est conseillé de tester la commande ou la bibliothèque d'archivage proposée pour s'assurer, qu'en effet, elle n'écrase pas un fichier existant
    Dans de rare cas, PostgreSQL pourrait tenter
    d'archiver de nouveau un journal de transaction qui a déjà été archivé.?
    Par exemple, si le système s'arrête brutalement avant que le serveur ait
    pu enregistrer de manière durable le succès de l'archivage, le serveur
    tentera d'archiver de nouveau le fichier après avoir redémarré (en supposant
    que l'archivage est toujours activé). Quand une commande ou une bibliothèque
    d'archivage rencontre un fichier existant, il doit renvoyer respectivement
    le statut zéro ou true si le journal a un contenu
    identique au journal archivé et que l'archive actuelle est correctement
    enregistré sur disque. Si un fichier pré-existant contient un contenu différent
    du journal à archiver, la commande d'archivage ou la bibliothèque
    doivent renvoyer respectivement un statut différent de
    zéro ou false.
   
    La commande d'exemple pour Unix ci-dessus évite d'écraser une archive pré-existante
    grâce à l'étape test
    séparée. Sur certaines plateformes Unix, la commande cp
    dispose d'une option, comme -i pouvant être utilisé pour
    faire la même chose, mais en moins verbeux. Cependant, vous ne devriez pas
    vous baser là-dessus sans vous assurer que le code de sortie renvoyé est le
    bon. (En particulier, la commande cp de GNU renvoie un
    code zéro quand -i est utilisé et que le fichier cible
    existe déjà, ce qui n'est pas le comportement désiré.)
   
    Lors de la conception de votre configuration d'archivage, il faut considérer
    ce qui peut se produire si la commande ou la bibliothèque d'archivage échoue
    de façon répétée, que ce soit parce qu'une intervention de l'opérateur
    s'avère nécessaire ou par manque d'espace dans le répertoire d'archivage.
    Ceci peut arriver, par exemple, lors de l'écriture sur une cartouche sans
    changeur automatique ; quand la cartouche est pleine, rien ne peut être
    archivé tant que la cassette n'est pas changée. Toute erreur ou requête à un
    opérateur humain doit être rapportée de façon appropriée pour que la
    situation puisse être résolue rapidement. Le répertoire
    pg_wal/ continue à se remplir de fichiers de segment
    WAL jusqu'à la résolution de la situation.(Si le système de fichiers
    contenant pg_wal/ se remplit,
    PostgreSQL s'arrête en mode PANIC. Aucune
    transaction validée n'est perdue mais la base de données est inaccessible
    tant que de l'espace n'a pas été libéré.)
   
    La vitesse de la commande ou de la bibliothèque d'archivage n'est pas
    importante, tant qu'elle suit le rythme de génération des journaux de
    transactions du serveur. Les opérations normales continuent même si le
    processus d'archivage est un peu plus lent. Si l'archivage est
    significativement plus lent, alors la quantité de données qui peut être
    perdue croît. Cela signifie aussi que le répertoire
    pg_wal/ contient un grand nombre de fichiers segment
    non archivés, qui peuvent finir par remplir l'espace disque disponible. Il
    est conseillé de surveiller le processus d'archivage pour s'assurer que tout
    fonctionne normalement.
   
    Lors de l'écriture de la commande ou de la bibliothèque d'archivage, il faut
    garder à l'esprit que les noms de fichier à archiver peuvent contenir
    jusqu'à 64 caractères et être composés de toute combinaison de lettres
    ASCII, de chiffres et de points. Il n'est pas nécessaire de conserver le
    chemin relatif original (%p) mais il est nécessaire de se
    rappeler du nom du fichier (%f).
   
    Bien que l'archivage des journaux de transactions autorise à restaurer
    toute modification réalisée sur les données de la base, il ne restaure
    pas les modifications effectuées sur les fichiers de configuration
    (c'est-à-dire postgresql.conf,
    pg_hba.conf et pg_ident.conf)
    car ceux-ci sont édités manuellement et non au travers d'opérations SQL.
    Il est souhaitable de conserver les fichiers de configuration à un
    endroit où ils sont sauvegardés par les procédures standard de sauvegarde
    du système de fichiers. Voir la Section 19.2 pour savoir comment modifier
    l'emplacement des fichiers de configuration.
   
    La commande ou la bibliothèque d'archivage n'est appelée que sur les
    fichiers segments WAL complets. Du coup, si le serveur engendre peu de
    trafic dans les journaux de transactions (ou qu'il y a des périodes de calme
    où le trafic est léger), il peut y avoir un long délai entre la fin d'une
    transaction et son enregistrement garanti dans le stockage d'archive. Pour
    placer une limite sur l'ancienneté des données archivées, il faut configurer
    archive_timeout, ce qui permet de forcer le serveur à
    changer de fichier segment WAL passé ce délai. Les fichiers archivés lors
    d'un tel forçage ont toujours la même taille que les fichiers complets.  Il
    est donc déconseillé de configurer un délai
    archive_timeout trop court  --  cela fait grossir
    anormalement le stockage. Une minute pour archive_timeout
    est généralement raisonnable.
   
    De plus, le changement d'un segment peut être forcé manuellement avec
    pg_switch_wal. Cela permet de s'assurer qu'une
    transaction tout juste terminée est archivée aussi vite que possible.
    D'autres fonctions utilitaires relatives à la gestion des journaux de
    transactions sont disponibles dans Tableau 9.95.
   
    Quand wal_level est configuré à la valeur
    minimal, certaines commandes SQL sont optimisées pour
    éviter la journalisation des transactions, de la façon décrite dans Section 14.4.7. Si l'archivage ou la réplication en flux sont
    activés lors de l'exécution d'une de ces instructions, les journaux de
    transaction ne contiennent pas suffisamment d'informations pour une
    restauration via les archives. (La restauration après un arrêt brutal n'est
    pas affectée.) Pour cette raison, wal_level ne peut être
    modifié qu'au lancement du serveur. Néanmoins,
    archive_command et archive_library
    peut être modifié par rechargement du fichier de configuration. Si vous
    archivez via le shell et souhaitez arrêter temporairement l'archivage, une
    façon de le faire est de peut placer une chaîne vide ('')
    dans archive_command.  Les journaux de transactions sont
    alors accumulés dans pg_wal/ jusqu'au rétablissement
    d'un paramètre archive_command fonctionnel.
   
La manière la plus simple pour effectuer une sauvegarde revient à utiliser l'outil pg_basebackup. Il peut créer une sauvegarde de base sous la forme soit de fichiers standards, soit d'une archive tar. Pour les cas plus complexes, il est possible de réaliser une sauvegarde de base en utilisant l'API bas niveau (voir Section 25.3.4).
    La durée d'une sauvegarde de base n'est pas toujours un critère
    déterminant. Toutefois, si vous exploitez votre serveur avec l'option
    full_page_writes désactivée, vous constaterez une
    baisse des performances lorsque la sauvegarde est effectuée car l'option
    full_page_writes est activée de force pendant les
    opérations de sauvegarde.
   
    Pour utiliser une sauvegarde, vous devez conserver tous les fichiers
    segments WAL générés pendant et après la sauvegarde des fichiers. Pour
    vous aider dans cette tâche, le processus de sauvegarde crée un
    fichier historique de sauvegarde qui est
    immédiatement enregistré dans la zone d'archivage des journaux de
    transactions. Le nom de ce fichier reprend le nom du premier fichier
    segment WAL que vous devez conserver. Par exemple, si le premier fichier
    segment WAL à garder est 0000000100001234000055CD,
    alors le fichier historique de sauvegarde sera nommé de la manière
    suivante 0000000100001234000055CD.007C9330.backup.
    (La seconde partie du nom de fichier indique la position exacte à
    l'intérieur du fichier segment WAL. Cette information peut être ignorée.)
    Une fois que vous avez archivé avec précaution la sauvegarde de base et
    les fichiers segments WAL générés pendant la sauvegarde (tel qu'indiqué
    par le fichier historique de sauvegarde), tous les fichiers segments WAL
    antérieurs ne sont plus nécessaires pour restaurer votre sauvegarde de
    base. Ils peuvent être supprimés. Toutefois, il est conseillé de
    conserver plusieurs groupes de sauvegardes pour être absolument certain
    de récupérer vos données.
   
Le fichier historique de sauvegarde est un simple fichier texte. Il contient le label que vous avez attribué à l'opération pg_basebackup, ainsi que les dates de début, de fin et la liste des fichiers segments WAL de la sauvegarde. Si vous avez utilisé le label pour identifier le fichier de sauvegarde associé, alors le fichier historique vous permet de savoir quel fichier de sauvegarde vous devez utiliser pour la restauration.
Puisque vous devez archiver tous les fichiers segments WAL depuis votre dernière sauvegarde de base, l'intervalle entre deux sauvegardes de base doit être déterminé en fonction de l'espace de stockage que vous avez alloué pour l'archivage des fichiers segments WAL. Vous devez également prendre en compte le temps de restauration (le système devra rejouer tous les fichiers segments WAL, cela prendra un certain temps si la sauvegarde de base est ancienne).
    Vous pouvez utiliser pg_basebackup pour réaliser
    une sauvegarde incrémentale en spécifiant l'option
    --incremental. Vous devez préciser comme argument
    de --incremental le manifeste de sauvegarde d'une
    précédente sauvegarde du même serveur. Dans la sauvegarde résultante,
    les fichiers ne correspondant pas à des relations seront inclus dans leur
    intégralité, mais certains fichiers de relations seront remplacés par des
    fichiers incrémentaux, plus petits, contenant uniquement les blocs
    modifiés depuis la sauvegarde précédente, et suffisamment de métadonnées
    pour reconstruire la version courante du fichier.
   
    Pour trouver les blocs à sauvegarder, le serveur
    utilise les résumés de journaux de transactions, résumés stockés
    dans le sous-répertoire pg_wal/summaries du
    répertoire des données. Si les fichiers résumés requis sont absents,
    toute tentative de sauvegarde incrémentale échouera. Les résumés présents
    dans ce répertoire doivent couvrir tous les LSN depuis le LSN de début
    de la sauvegarde précédente. Comme le serveur recherche les résumés des
    journaux de transaction juste après avoir établi le LSN de départ de
    la sauvegarde courante, les fichiers de résumé nécessaires ne seront
    pas instantanément présents sur disque, mais le serveur attendra
    l'arrivée des fichiers manquants. Ceci aide aussi si le processus
    résumant les journaux a pris du retard. Néanmoins, si les fichiers
    nécessaires ont déjà été supprimés, ou si le processus de résumé des
    journaux ne rattrape pas son retard suffisamment rapidement, la
    sauvegarde incrémentale échouera.
   
    Lors de la restauration d'une sauvegarde incrémentale, il sera nécessaire
    d'avoir non seulement la sauvegarde incrémentale, mais aussi toutes les
    sauvegardes précédentes requises pour fournir les blocs absents de la
    sauvegarde incrémentale. Voir pg_combinebackup pour
    plus d'informations sur ce prérequis. Notez qu'il existe des restrictions
    sur l'utilisation de pg_combinebackup quand le statut
    des sommes de contrôle sur l'instance a changé ; voir les
    limitations de
    pg_combinebackup.
   
    Notez que tous les prérequis sur l'utilisation d'une sauvegarde complète
    s'appliquent aussi à une sauvegarde incrémentale. Par exemple, vous aurez
    besoin de tous les segments de fichiers WAL générés pendant et après la
    sauvegarde du système de fichiers, ainsi que de tous les fichiers
    d'historique. Vous aurez toujours encore besoin de créer un fichier
    recovery.signal (ou standby.signal)
    et d'exécuter la restauration, comme décrit dans Section 25.3.5. Le besoin des sauvegardes précédentes
    au moment de la restauration et l'utilisation de
    pg_combinebackup est une condition supplémentaire en plus
    de tout le reste. Gardez en tête que
    PostgreSQL, seul, ne sait pas
    détecter quelles sont les sauvegardes nécessaires à la restauration d'une
    sauvegarde incrémentale postérieure. Vous devez garder la trace des liens entre
    vos sauvegardes complète et incrémentales, et vous assurer de ne pas
    supprimer les sauvegardes précédentes si elles sont nécessaires pour
    restaurer des sauvegardes incrémentales ultérieures.
   
Les sauvegardes incrémentales n'ont d'interêt que pour des bases de données relativement volumineuses, où une portion significative des données ne change pas, ou change à un faible rythme. Pour une petite base, il est plus simple d'oublier les sauvegardes incrémentales et de rester sur des sauvegardes complètes, bien plus simples à gérer. Pour une base de données volumineuse et lourdement modifiée, les sauvegardes incrémentales ne seront pas beaucoup plus petites que les sauvegardes complètes.
Une sauvegarde incrémentale est seulement possible si le rejeu peut commencer à partir un checkpoint ultérieur à la précédente sauvegarde dont il dépend. Si vous réalisez une sauvegarde incrémentale à partir du serveur primaire, cette condition est toujours satisfaite car chaque sauvegarde déclenche un nouveau checkpoint. Sur un serveur secondaire, le rejeu commence à partir du restartpoint le plus récent. De ce fait, une sauvegarde incrémentale d'un serveur secondaire peut échouer s'il y a eu très peu d'activité depuis la sauvegarde précédente car aucun nouveau restartpoint n'aura été créé.
Au lieu de prendre une sauvegarde de base complète ou incrémentale avec pg_basebackup, vous pouvez faire une sauvegarde de base en utilisant l'API bas niveau. Cette procédure contient quelques étapes supplémentaires à la méthode pg_basebackup mais reste relativement simple. Il est très important de dérouler ces étapes dans l'ordre, et de vérifier que chacune s'est déroulée correctement avant de passer à la suivante.
Plusieurs sauvegardes peuvent s'exécuter en même temps (celles démarrées en utilisant cette API comme celles démarrées avec pg_basebackup).
S'assurer que l'archivage des journaux de transactions est activé et fonctionnel.
        Se connecter au serveur (peu importe la base) en tant qu'utilisateur
        ayant les droits d'exécuter la fonction
        pg_backup_start (donc soit un superutilisateur,
        soit un utilisateur ayant gagné le droit EXECUTE
        sur cette fonction) et lancer la commande :
        
SELECT pg_backup_start(label => 'label', fast => false);
        où label est une chaîne utilisée pour identifier de
        façon unique l'opération de sauvegarde. La connexion appelant
        pg_backup_start doit être maintenue jusqu'à la
        fin de la sauvegarde. Dans le cas contraire, la sauvegarde sera
        automatiquement avortée.
       
        Les sauvegardes en ligne sont toujours démarrées au début d'un
        checkpoint.  Par défaut, pg_backup_start attendra
        le prochain checkpoint planifié pour se terminer, ce qui peut prendre un
        long moment (voir les paramètres de configuration checkpoint_timeout et checkpoint_completion_target). C'est généralement
        préférable car cela minimise l'impact sur le système en cours
        d'exécution. Si vous voulez démarrer la sauvegarde aussi vite que
        possible, passez true sur le second paramètre de
        pg_backup_start et il demandera un checkpoint
        immédiat, qui finira aussi rapidement que possible en utilisant autant
        de bande passante disque que possible.
       
Effectuer la sauvegarde à l'aide de tout outil de sauvegarde du système de fichiers, tel tar ou cpio (mais ni pg_dump ni pg_dumpall). Il n'est ni nécessaire ni désirable de stopper les opérations normales de la base de données pour cela. Voir la section Section 25.3.4.1 pour les considérations à prendre en compte durant cette sauvegarde.
Dans la même connexion que précédemment, lancer la commande :
SELECT * FROM pg_backup_stop(wait_for_archive => true);
        Cela met fin au processus de sauvegarde. Sur un serveur primaire, cela
        réalise aussi une bascule automatique au prochain segment de journal
        de transactions. Sur un serveur secondaire, il n'est pas possible de
        basculer automatiquement les segments des journaux de transactions,
        donc vous pourriez vouloir utiliser
        pg_switch_wal sur le primaire pour réaliser une
        bascule manuelle. Cette bascule est nécessaire pour permettre au
        dernier fichier de segment WAL écrit pendant la sauvegarde d'être
        immédiatement archivable.
       
        La fonction pg_backup_stop retournera une ligne
        avec trois valeurs. Le second de ces champs devra être écrit dans un
        fichier nommé backup_label dans le répertoire
        racine de la sauvegarde. Le troisième champ devra être écrit dans un
        fichier nommé tablespace_map sauf si le champ
        est vide. Ces fichiers sont vitaux pour le fonctionnement de la
        sauvegarde et doivent être écrits octet par octet sans modification,
        ce qui nécessite de les ouvrir en mode binaire.
       
        Une fois que les fichiers segment WAL utilisés lors de la sauvegarde
        sont archivés, c'est terminé. Le fichier identifié par le résultat de
        pg_backup_stop est le dernier segment nécessaire
        pour produire un jeu complet de fichiers de sauvegarde. Sur un serveur
        primaire, si archive_mode est activé et que le
        paramètre wait_for_archive est activé (valeur
        true), pg_backup_stop ne rend
        pas la main avant que le dernier segment n'ait été archivé.  Sur un
        serveur secondaire, le paramètre archive_mode doit
        valoir always pour que la fonction
        pg_backup_stop soit en attente. L'archivage de ces
        fichiers est automatique puisque archive_command ou
        archive_library est déjà configuré. Dans la plupart
        des cas, c'est rapide, mais il est conseillé de surveiller le système
        d'archivage pour s'assurer qu'il n'y a pas de retard. Si le processus
        d'archivage a pris du retard en raison d'échecs de la commande ou de la
        bibliothèque d'archivage, il continuera d'essayer jusqu'à ce que
        l'archivage réussisse et que la sauvegarde soit complète. Pour
        positionner une limite au temps d'exécution de
        pg_backup_stop, il faut positionner
        statement_timeout à une valeur appropriée, mais il
        faut noter que si pg_backup_stop est interrompu à
        cause de cette configuration, la sauvegarde peut ne pas être correcte.
       
        Si le processus de sauvegarde surveille et s'assure que tous les
        fichiers segments WAL nécessaires à la sauvegarde soient archivés
        avec succès, le paramètre wait_for_archive
        (positionné à true par défaut) peut être positionné à false pour que
        pg_backup_stop renvoie la main dès que
        l'enregistrement de fin de sauvegarde est écrit dans le journal de
        transaction en cours. Par défaut, pg_backup_stop
        attendra jusqu'à ce que tous les journaux de transactions aient été
        archivés, ce qui peut prendre un certain temps.  Cette option doit
        être utilisée avec précaution : si l'archivage des journaux de
        transactions n'est pas supervisé correctement, alors la sauvegarde
        pourrait ne pas inclure tous les fichiers segments WAL, et serait
        donc incomplète et impossible à restaurer.
       
Certains outils de sauvegarde de fichiers émettent des messages d'avertissement ou d'erreur si les fichiers qu'ils essaient de copier sont modifiés au cours de la copie. Cette situation, normale lors de la sauvegarde d'une base active, ne doit pas être considérée comme une erreur ; il suffit de s'assurer que ces messages puissent être distingués des autres messages. Certaines versions de rsync, par exemple, renvoient un code de sortie distinct en cas de « disparition de fichiers source ». Il est possible d'écrire un script qui considère ce code de sortie comme normal.
     De plus, certaines versions de GNU tar
     retournent un code d'erreur qu'on peut confondre avec une erreur fatale
     si le fichier a été tronqué pendant sa copie par
     tar. Heureusement, les versions 1.16 et
     suivantes de GNU tar retournent 1 si le
     fichier a été modifié pendant la sauvegarde et 2 pour les autres
     erreurs. Avec GNU tar version 1.23 et les
     versions ultérieures, vous pouvez utiliser les options d'avertissement
     --warning=no-file-changed
     --warning=no-file-removed pour cacher les messages
     d'avertissement en relation.
    
     La sauvegarde doit inclure tous les fichiers du répertoire dde l'instance
     de bases de données(/usr/local/pgsql/data, par
     exemple). Si des tablespaces qui ne se
     trouvent pas dans ce répertoire sont utilisés, il ne faut pas oublier de
     les inclure (et s'assurer également que la sauvegarde archive les liens
     symboliques comme des liens, sans quoi la restauration va corrompre les
     tablespaces).
    
     Néanmoins, les fichiers du sous-répertoire pg_wal/,
     contenu dans le répertoire de l'instance, devraient être omis. Ce léger
     ajustement permet de réduire le risque d'erreurs lors de la
     restauration. C'est facile à réaliser si pg_wal/
     est un lien symbolique vers quelque endroit extérieur au répertoire de
     l'instance, ce qui est une configuration courante pour des raisons de
     performance. Il peut être aussi intéressant d'exclure
     postmaster.pid et
     postmaster.opts, qui enregistrent des informations
     sur le postmaster en cours d'exécution, mais
     pas sur le postmaster qui va utiliser cette
     sauvegarde. De plus, ces fichiers peuvent poser problème à
     pg_ctl.
    
     C'est souvent une bonne idée d'omettre de la sauvegarde les fichiers
     provenant du répertoire pg_replslot/ de l'instance,
     pour que les slots de réplication existant sur le primaire ne deviennent
     pas partie intégrante de la sauvegarde. Dans le cas contraire,
     l'utilisation de la sauvegarde pour créer un secondaire pourrait
     résulter en une rétention infinie des journaux de transactions sur le
     secondaire et aussi de la fragmentation sur le primaire si les messages
     de retour d'un secondaire en Hot Standby sont activés, parce que les
     clients qui utilisent ces slots de réplication se connecteront toujours
     et mettront à jour les slots sur le primaire et non pas sur le
     secondaire. Même si la sauvegarde a pour but d'être utilisée pour la
     création d'un nouveau primaire, copier les slots de réplication n'est
     pas un comportement attendu car il n'a pas de raison d'être, le contenu
     de ces slots sera très probablement obsolète au moment où le nouveau
     primaire sera en ligne.
    
     Le contenu des répertoires pg_dynshmem/,
     pg_notify/, pg_serial/,
     pg_snapshots/, pg_stat_tmp/ et
     pg_subtrans/ (mais pas les répertoires eux-même)
     peut être exclu de la sauvegarde puisqu'il sera réinitialisé au
     démarrage de postmaster.
    
     N'importe quel fichier ou répertoire commençant par
     pgsql_tmp peut être exclu de la sauvegarde. Ces
     fichiers sont supprimés au démarrage de postmaster et les répertoires
     seront recréés si nécessaire.
    
     Les fichiers pg_internal.init peuvent être omis de
     la sauvegarde quand un fichier de ce nom est trouvé. Ces fichiers
     contiennent les données du cache des relations qui est toujours
     reconstruit lors de la restauration.
    
     Le fichier de label de la sauvegarde inclut la chaîne de label passée à
     pg_backup_start, l'heure à laquelle
     pg_backup_start a été exécutée et le nom du fichier
     segment WAL initial. En cas de confusion, il est ainsi possible de
     regarder dans ce fichier de label et de déterminer avec précision de
     quelle session de sauvegarde il provient. Le fichier des tablespaces
     inclut les noms des liens symboliques s'ils existent dans le répertoire
     pg_tblspc/ et le chemin complet de chaque lien
     symbolique. Néanmoins, ces fichiers n'existent pas uniquement pour vous
     informer. Leurs présences et contenus sont critiques au bon déroulement
     du processus de restauration.
    
     Il est aussi possible de faire une sauvegarde alors que le serveur est
     arrêté. Dans ce cas, les fonctions pg_backup_start
     et pg_backup_stop ne peuvent pas être utilisées.
     L'utilisateur doit alors se débrouiller pour identifier les fichiers de
     sauvegarde et déterminer jusqu'où remonter avec les fichiers segments
     WAL associés. Il est généralement préférable de suivre la procédure
     d'archivage continu décrite ci-dessus.
    
Le pire est arrivé et il faut maintenant repartir d'une sauvegarde. Voici la procédure :
Arrêter le serveur s'il est en cours d'exécution.
       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. Cette
       précaution nécessite qu'un espace suffisant sur le système soit
       disponible pour contenir deux copies de la base de données existante.
       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 de
       transactions qui n'ont
       pas été archivés avant l'arrêt du serveur.
      
Effacer tous les fichiers et sous-répertoires existant sous le répertoire des données de l'instance et sous les répertoires racines des tablespaces.
       Si vous restaurez une sauvegarde complète, vous pouvez restaurer les
       fichiers de la base directement dans les répertoires cibles.
       Il faut veiller à ce qu'ils soient restaurés avec le bon
       propriétaire (l'utilisateur système de la base de données, et non pas
       root !) et avec les bons droits. Si des
       tablespaces sont utilisés, il faut
       s'assurer que les liens symboliques dans
       pg_tblspc/ ont été correctement restaurés.
      
Si vous restaurez une sauvegarde incrémentale, vous aurez besoin de restaurer la sauvegarde incrémentale et toutes les sauvegardes précédentes qui en dépendant, directement ou indirectement, sur la machine où vous voulez restaurer. Ces sauvegardes devront être placées dans des répertoires séparées, pas dans les répertoires cibles où vous voudrez exécuter le serveur. Une fois ceci fait, utilisez pg_combinebackup pour récupérer les données de la sauvegarde complète et des sauvegardes incrémentales suivantes, pour écrire la sauvegarde complète synthétique dans les répertoires cibles. Comme ci-dessus, vérifiez que les droits et les liens des tablespaces sont corrects.
       Supprimer tout fichier présent dans pg_wal/ ;
       ils proviennent de la sauvegarde et sont du coup probablement
       obsolètes. Si pg_wal/ n'a pas été archivé, il
       suffit de recréer ce répertoire en faisant attention à le créer en
       tant que lien symbolique, si c'était le cas auparavant.
      
       Si des fichiers segments WAL non archivés ont été sauvegardés dans
       l'étape 2, les copier dans pg_wal/. Il est
       préférable de les copier plutôt que de les déplacer afin qu'une
       version non modifiée de ces fichiers soit toujours disponible si un
       problème survient et qu'il faille recommencer.
      
       Configurer les commandes de restauration dans
       postgresql.conf(voir Section 19.5.5) et créer un fichier
       recovery.signal dans le répertoire des données de
       l'instance. De plus, 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 restauration a réussi.
      
       Démarrer le serveur. Le serveur se trouve alors en mode restauration et
       commence la lecture des fichiers segments WAL archivés dont il a
       besoin. Si la restauration se termine sur une erreur externe, le
       serveur peut tout simplement être relancé. Il continue alors la
       restauration. À la fin du processus de restauration, le serveur
       supprime le fichier recovery.signal(pour éviter
       de retourner accidentellement en mode de restauration), puis passe en
       mode de fonctionnement normal.
      
       Inspecter le contenu de la base de données pour s'assurer que la
       restauration a bien fonctionné. Dans le cas contraire, retourner à
       l'étape 1. Si tout va bien, le fichier
       pg_hba.conf peut être restauré pour autoriser les
       utilisateurs à se reconnecter.
      
    Le point clé de tout ceci est la configuration de la restauration qui
    décrit comment et jusqu'où restaurer. La seule chose qu'il faut
    absolument préciser dans postgresql.conf, c'est la
    valeur du paramètre restore_command qui indique à
    PostgreSQL comment récupérer les fichiers
    segments WAL archivés. À l'instar d'archive_command,
    c'est une chaîne de commande shell. Elle peut contenir
    %f, qui est remplacé par le nom du journal de
    transactions souhaité,
    et %p, qui est remplacé par le chemin du répertoire où
    copier le journal de transactions.(Le nom du chemin est relatif au répertoire de travail
    du serveur, c'est-à-dire le répertoire des données du cluster.) Pour
    écrire le caractère % dans la commande, on utilise
    %%. La commande la plus simple ressemble à :
    
restore_command = 'cp /mnt/serveur/répertoire_archive/%f %p'
    qui copie les fichiers segments WAL précédemment archivés à partir du
    répertoire /mnt/serveur/répertoire_archive.  Il est
    toujours possible d'utiliser une commande plus compliquée, voire même un
    script shell qui demande à l'utilisateur de monter la cassette
    appropriée.
   
Il est important que la commande renvoie un code de sortie différent de zéro en cas d'échec. Des fichiers absents de l'archive seront demandés à la commande ; elle doit renvoyer autre chose que zéro dans ce cas. Ce n'est pas une condition d'erreur. Une exception est possible si la commande a été terminée par un signal (autre que SIGTERM, qui est utilisé pour l'arrêt du serveur) ou par une erreur shell (comme une commande introuvable). Dans ces cas, la restauration va s'arrêter et le serveur ne démarrera plus.
    Tous les fichiers demandés ne seront pas des fichiers segments WAL ;
    vous pouvez aussi vous attendre à des demandes de fichiers suffixés par
    .history. Il faut également garder à l'esprit que le
    nom de base du chemin %p diffère de
    %f ; ils ne sont pas interchangeables.
   
    Les segments WAL qui ne se trouvent pas dans l'archive sont recherchés
    dans pg_wal/ ; cela autorise l'utilisation de
    segments récents non archivés. Néanmoins, les segments disponibles dans
    l'archive sont utilisés de préférence aux fichiers contenus dans
    pg_wal/.
   
    Normalement, la récupération traite tous les segments WAL disponibles,
    restaurant du coup la base de données à l'instant présent (ou aussi
    proche que possible, en fonction des fichiers segments WAL disponibles).
    Une récupération normale se finit avec un message « fichier non
    trouvé », le texte exact du message d'erreur dépendant du choix de
    restore_command. Un message d'erreur au début de la
    restauration peut également apparaître concernant un fichier nommé dont
    le nom ressemble à 00000001.history. Ceci est aussi
    normal et n'indique pas un problème dans les situations de restauration
    standards. Voir Section 25.3.6 pour plus
    d'informations.
   
Pour restaurer jusqu'à un moment précis (avant que le DBA junior n'ait supprimé la table principale par exemple), il suffit d'indiquer le point d'arrêt requis. Le point d'arrêt, aussi nommé « cible de récupération » (« recovery target » dans la version originale) , peut être précisé par une combinaison de date et d'heure, par un point de restauration nommé ou par un identifiant de transaction. Actuellement, seules les options date/heure et point de restauration nommé sont vraiment utilisables car il n'existe pas d'outils permettant d'identifier avec précision l'identifiant de transaction à utiliser.
     Le point d'arrêt doit être postérieur à la fin de la sauvegarde de la
     base (le moment où pg_backup_stop se termine). Une
     sauvegarde ne peut pas être utilisée pour repartir d'un instant où elle
     était encore en cours (pour ce faire, il faut récupérer la sauvegarde
     précédente et rejouer à partir de là).
    
    Si la restauration fait face à une corruption des données des journaux de
    transactions, le rejeu s'interrompt juste avant la corruption détectée et
    le serveur ne démarre pas. Dans un tel cas, le processus de restauration
    peut alors être ré-exécuté à partir du début en précisant une
    « cible de restauration » antérieure au point de corruption
    pour permettre à cette dernière de se terminer correctement. Si la
    restauration échoue pour une raison externe (arrêt brutal du système ou
    archive devenue inaccessible), la restauration peut être simplement
    relancée. Elle redémarre alors quasiment là où elle a échoué. Le
    redémarrage de la restauration fonctionne comme les checkpoints du
    déroulement normal : le serveur force une écriture régulière de son
    état sur les disques et actualise alors le fichier
    pg_control pour indiquer que les données déjà
    traitées des journaux de transactions n'ont plus à être parcourues.
   
La possibilité de restaurer la base de données à partir d'un instantané crée une complexité digne des histoires de science-fiction traitant du voyage dans le temps et des univers parallèles.
Par exemple, dans l'historique original de la base de données, supposez qu'une table critique ait été supprimée à 17h15 mardi soir, mais que personne n'ait réalisé cette erreur avant mercredi midi. Sans stress, la sauvegarde est récupérée et restaurée dans l'état où elle se trouvait à 17h14 mardi soir. La base est fonctionnelle. Dans cette histoire de l'univers de la base de données, la table n'a jamais été supprimée. Or, l'utilisateur réalise peu après que ce n'était pas une si grande idée et veut revenir à un quelconque moment du mercredi matin. Cela n'est pas possible, si, alors que la base de données est de nouveau fonctionnelle, elle réutilise certaines séquences de fichiers segments WAL qui permettent de retourner à ce point. Il est donc nécessaire de pouvoir distinguer les séries d'enregistrements des journaux de transactions engendrées après la restauration de l'instantané de celles issues de l'historique originel de la base.
    Pour gérer ces difficultés, PostgreSQL inclut
    la notion de lignes temporelles
    (ou timelines). Quand une récupération
    d'archive est terminée, une nouvelle ligne temporelle est créée pour
    identifier la série d'enregistrements de journaux de transactions
    produits après cette restauration. Le numéro d'identifiant de la timeline
    est inclus dans le nom des fichiers segments WAL. De ce fait, une
    nouvelle timeline ne réécrit pas sur les données engendrées par des
    timelines précédentes. Par exemple, dans le nom de journal
    0000000100001234000055CD, le début
    00000001 est l'identifiant de la timeline en hexadécimal.
    (Notez que, dans d'autres contexyes, comme les traces du serveur, les
    identifiants de timeline sont habituellement affichés en décimal.)
   
En fait, il est possible d'archiver plusieurs timelines différentes. Bien que cela semble être une fonctionnalité inutile, cela peut parfois sauver des vies. Dans une situation où l'instantané à restaurer n'est pas connu avec certitude, il va falloir tester les restaurations de différents instantanés jusqu'à trouver le meilleur. Sans les timelines, ce processus engendre vite un bazar ingérable. Avec les timelines, il est possible de restaurer n'importe quel état précédent, même les états de branches temporelles abandonnées.
Chaque fois qu'une nouvelle timeline est créée, PostgreSQL crée un fichier d'« historique des timelines » qui indique à quelle timeline il est attaché, et depuis quand. Ces fichiers d'historique sont nécessaires pour permettre au système de choisir les bons fichiers segments WAL lors de la restauration à partir d'une archive qui contient plusieurs timelines. Ils sont donc archivés comme tout fichier segment WAL. Puisque ce sont de simples fichiers texte, il est peu coûteux et même judicieux de les conserver indéfiniment(contrairement aux fichiers segments, bien plus volumineux). Il est possible d'ajouter des commentaires au fichier d'historique expliquant comment et pourquoi cette timeline a été créée. De tels commentaires s'avèrent précieux lorsque l'expérimentation conduit à de nombreuses timelines.
    Par défaut, la restauration s'effectue jusqu'à la dernière timeline
    trouvée dans l'archive. Si vous souhaitez effectuer la restauration
    uniquement pour la timeline de la sauvegarde ou jusqu'à une timeline
    précise (c'est-à-dire retourner à un état enregistré après une tentative
    de restauration), il faut préciser current ou
    l'identifiant de la timeline cible dans recovery_target_timeline. Il n'est pas possible de
    restaurer dans des timelines antérieures à la sauvegarde.
   
Quelques conseils de configuration de l'archivage continu sont donnés ici.
Il est possible d'utiliser les capacités de sauvegarde de PostgreSQL pour produire des sauvegardes autonomes à chaud. Ce sont des sauvegardes qui ne peuvent pas être utilisées pour la restauration à un instant donné, mais ce sont des sauvegardes qui sont typiquement plus rapides à obtenir et à restaurer que celles issues de pg_dump. (Elles sont aussi bien plus volumineuses qu'un export pg_dump, il se peut donc que l'avantage de rapidité soit négatif.)
     Comme pour les sauvegardes de base, la manière la plus simple de créer
     une sauvegarde à chaud autonome est d'utiliser l'outil pg_basebackup. Si vous ajoutez le paramètre
     -X au lancement de la sauvegarde, tout l'historique
     des transactions nécessaire sera inclus automatiquement dans la
     sauvegarde et vous n'aurez pas d'action supplémentaire à effectuer pour
     restaurer votre sauvegarde.
    
Si la taille du stockage des archives est un problème, vous pouvez utiliser gzip pour compresser les fichiers archives :
archive_command = 'gzip < %p > /mnt/server/archivedir/%f'
Vous aurez alors besoin d'utiliser gunzip pendant la restauration :
restore_command = 'gunzip < /mnt/server/archivedir/%f.gz > %p'
archive_command #
     Nombreux sont ceux qui choisissent d'utiliser des scripts pour définir
     leur archive_command, de sorte que leur
     postgresql.conf semble très simple :
     
archive_command = 'local_backup_script.sh "%p" "%f"'
Utiliser un script séparé est conseillé à chaque fois qu'il est envisagé d'utiliser plusieurs commandes pour le processus d'archivage. Ainsi, toute la complexité est gérée dans le script qui peut être écrit dans un langage de scripts populaires comme bash ou perl.
Quelques exemples de besoins résolus dans un script :
copier des données vers un stockage distant ;
copier les journaux de transactions en groupe pour qu'ils soient transférés toutes les trois heures plutôt qu'un à la fois ;
s'interfacer avec d'autres outils de sauvegarde et de restauration ;
s'interfacer avec un outil de surveillance pour y renvoyer les erreurs.
      Lors de l'utilisation d'un script pour le paramètre
      archive_command, il est préférable d'activer logging_collector. Tout message écrit sur
      stderr à partir du script apparaîtra ensuite
      dans les traces du serveur, permettant un diagnostic facilité de
      configurations complexes en cas de problème.
     
Au moment où ces lignes sont écrites, plusieurs limitations de la technique d'archivage en continu sont connues. Elles seront probablement corrigées dans une prochaine version :
       Si une commande CREATE
       DATABASE est exécutée alors qu'une sauvegarde est en
       cours, et que la base de données modèle utilisée par l'instruction
       CREATE DATABASE est à son tour modifiée pendant la
       sauvegarde, il est possible que la récupération propage ces
       modifications dans la base de données créée. Pour éviter ce risque,
       il est préférable de ne pas modifier les bases de données modèle lors
       d'une sauvegarde de base.
      
       Les commandes CREATE
       TABLESPACE sont tracées dans les journaux de
       transactions avec le chemin absolu et sont donc rejouées en tant que
       créations de tablespace suivant le
       même chemin absolu. Cela n'est pas forcément souhaitable si le
       journal de transactions est rejoué sur une autre machine. De plus, cela peut s'avérer
       dangereux même lorsque le journal de transactions est rejoué sur la même machine,
       mais dans un répertoire différent : la ré-exécution surcharge
       toujours le contenu du tablespace
       original. Pour éviter de tels problèmes, la meilleure solution
       consiste à effectuer une nouvelle sauvegarde de la base après la
       création ou la suppression de
       tablespace.
      
    De plus, il faut garder à l'esprit que le format actuel des journaux de
    transactions est extrêmement volumineux car il inclut de nombreuses
    images complètes des blocs disques. Ces images de bloc sont conçues pour
    supporter la restauration après un arrêt brutal, puisqu'il peut être
    nécessaire de corriger des blocs disque partiellement écrits. En fonction
    du matériel et des logiciels composant le système, le risque d'écriture
    partielle peut être suffisamment faible pour être ignoré, auquel cas le
    volume total des traces archivées peut être considérablement réduit par
    la désactivation des images de bloc à l'aide du paramètre full_page_writes(lire les notes et avertissements dans
    Chapitre 28 avant de le faire). Désactiver les images de bloc
    n'empêche pas l'utilisation des traces pour les opérations PITR. Un piste
    éventuelle de développement futur consiste à compresser les données des
    journaux de transactions archivés en supprimant les copies inutiles de
    blocs même si full_page_writes est actif. Entre temps,
    les administrateurs peuvent souhaiter réduire le nombre d'images de blocs
    inclus dans les journaux de transactions en augmentant autant que
    possible les paramètres d'intervalle entre les checkpoints.