Restauration, recover maximal

Perdre le minimum de transactions validées

      Erreur d'un administrateur, corruption d'un filesystem ou incident matériel...vous avez perdu votre cluster PostgreSQL. Il ne s'agit pas d'une erreur applicative, vous ne voulez pas faire revenir les bases en arrière. Le but va donc être de restituer le service en perdant un minimum de transactions validées et même, si possible, aucune.
      Le cluster est sauvegardé selon la méthode de sauvegarde distante, le RPO (recovery point objective, perte de données maximale admissible) doit être proche de 0.
      Tout d'abord, simulation d'incident :

-- serveur pgpr10 -- session utilisateur, postgres psql create table temoin(col timestamp); CREATE TABLE insert into temoin values(current_timestamp) returning *; col --------------------------- 2018-02-14 04:22:10.13207 (1 ligne) INSERT 0 1 \watch 1 ... mer. 14 févr. 2018 04:23:31 CET (chaque 1s) col ---------------------------- 2018-02-14 04:23:31.204303 (1 ligne) ... -- incident majeur, root pg_lsclusters rm -fr /var/lib/postgresql/10/apptra001/* -- dans la session de l'utilisateur, postgres mer. 14 févr. 2018 11:12:23 CET (chaque 1s) col ---------------------------- 2018-02-14 11:12:23.404273 (1 ligne) ATTENTION: arrêt de la connexion à cause de l'arrêt brutal d'un autre processus serveur DéTAIL : Le postmaster a commandé à ce processus serveur d'annuler la transaction courante et de quitter car un autre processus serveur a quitté anormalement et qu'il existe probablement de la mémoire partagée corrompue. ASTUCE : Dans un moment, vous devriez être capable de vous reconnecter à la base de données et de relancer votre commande. la connexion au serveur a été coupée de façon inattendue Le serveur s'est peut-être arrêté anormalement avant ou durant le traitement de la requête. La connexion au serveur a été perdue. Tentative de réinitialisation : échec.


      Au vu de l'incident, peut-être aurions-nous la possibilité d'agir via un utilitaire quelconque développé pour le type de filesystem sur lequel repose le cluster. Il faut toujours évaluer si une restauration est réellement nécessaire avant de se lancer. Nous allons ici supposer que nous ne disposons d'aucune solution en dehors d'une restauration depuis Barman :

-- serveur bapr, barman barman recover --remote-ssh-command "ssh postgres@pgpr10" apptra001 latest /var/lib/postgresql/10/apptra001 ... Your PostgreSQL server has been successfully prepared for recovery! -- serveur pgpr10, root vi /var/lib/barman/10/apptra001/recovery.conf, ajout de standby_mode = on # The 'barman-wal-restore' command is provided in the 'barman-cli' package restore_command = 'barman-wal-restore -U barman bapr apptra001 %f %p' standby_mode = on pg_ctlcluster 10 apptra001 start pg_lsclusters Ver Cluster Port Status Owner Data directory Log file 10 apptra001 5432 online,recovery postgres /var/lib/postgresql/10/apptra001 /var/log/postgresql/postgresql-10-apptra001.log tail -f /var/log/postgresql/postgresql-10-apptra001.log 2018-02-14 11:47:27.775 CET [1013] LOG: restauration du journal de transactions « 000000010000000000000007 » à partir de l'archive 2018-02-14 11:47:29.126 CET [1013] LOG: restauration du journal de transactions « 000000010000000000000008 » à partir de l'archive ERROR: WAL file '000000010000000000000009' not found in server 'apptra001' (SSH host: 192.168.56.220) ERROR: Remote 'barman get-wal' command has failed! -- serveur pgpr10, postgres psql select max(col) from temoin; max ---------------------------- 2018-02-14 10:54:18.817031 (1 ligne)


      La restauration et le recover se sont bien passés mais nous pouvons constater que nous n'avons travaillé qu'avec les WAL archivés (jusqu'au WAL 000000010000000000000008 inclus).
      La dernière transaction dont nous disposons date de 10h54 alors que nous avons pu travailler jusque 11h12. C'est mieux que rien mais nous pouvons aller plus loin puisque nous disposons du WAL courant au moment de l'incident (ici le 000000010000000000000009) grâce au streaming WAL effectué vers Barman. Avec standby_mode à on, le cluster attend des informations de journalisation en mode recover comme le ferait un cluster de secours. Nous allons fournir manuellement ces informations en copiant le WAL qui était en cours de streaming dans le dossier pg_wal :

-- serveur bapr, barman cd /var/lib/barman/apptra001/streaming ls -ltr total 16384 -rw------- 1 barman barman 16777216 févr. 14 11:12 000000010000000000000009.partial scp 000000010000000000000009.partial postgres@pgpr10:/var/lib/postgresql/10/apptra001/pg_wal/000000010000000000000009 -- serveur pgpr10, root vi /var/lib/barman/10/apptra001/recovery.conf, on ne garde que standby_mode=on standby_mode = on pg_ctlcluster 10 apptra001 restart tail -f /var/log/postgresql/postgresql-10-apptra001.log ... 2018-02-14 12:13:54.734 CET [2697] ATTENTION: le fichier de restauration « recovery.conf » n'a spécifié ni primary_conninfo ni restore_command 2018-02-14 12:13:54.734 CET [2697] ASTUCE : Le serveur de la base de données va régulièrement interroger le sous-répertoire pg_wal pour vérifier les fichiers placés ici. -- serveur pgpr10, postgres psql select max(col) from temoin; max ---------------------------- 2018-02-14 11:12:23.404273 (1 ligne) -- serveur pgpr10, root mv /var/lib/postgresql/10/apptra001/recovery.conf /var/lib/postgresql/10/apptra001/recovery.done mv /var/lib/postgresql/10/apptra001/postgresql.auto.conf.origin /var/lib/postgresql/10/apptra001/postgresql.auto.conf pg_ctlcluster 10 apptra001 restart pg_lsclusters Ver Cluster Port Status Owner Data directory Log file1 10 apptra001 5432 online postgres /var/lib/postgresql/10/apptra001 /var/log/postgresql/postgresql-10-apptra001.log tail -f /var/log/postgresql/postgresql-10-apptra001.log ... 2018-02-14 12:29:37.821 CET [3255] LOG: ré-exécution faite à 0/90FFC00 2018-02-14 12:29:37.821 CET [3255] LOG: la dernière transaction a eu lieu à 2018-02-14 11:12:23.404583+01 (moment de la journalisation) 2018-02-14 12:29:37.896 CET [3254] LOG: le système de bases de données est prêt pour accepter les connexions -- serveur bapr, barman barman receive-wal --create-slot apptra001 Creating physical replication slot 'barman' on server 'apptra001' Replication slot 'barman' created barman cron Starting WAL archiving for server apptra001 Starting streaming archiver for server apptra001 barman check apptra001 ...OK


      11h12min23s : nous n'avons dans cet exemple perdu aucune transaction. En pratique, lorsque le streaming WAL vers Barman n'est pas effectué de manière synchrone, quelques transactions peuvent être perdues en fonction de la latence réseau, de la charge etc. Si aucune transaction ne doit être perdue, il est possible de réaliser le streaming WAL de manière synchrone mais cela peut présenter d'autres inconvénients en termes de disponibilité (il est conseillé d'avoir plusieurs destinations pour le streaming WAL dans ce cas) et de performance.
      Après avoir constaté que tout est OK, rétablir l'archivage car Barman positionne archive_command=FALSE après une restauration afin d'éviter les confusions et les erreurs. Vous n'avez pas besoin de le faire manuellement car les fichiers de configuration originaux sont disponibles avec l'extension .origin.
      Vérifier également que la sauvegarde est toujours opérationnelle au niveau de Barman, un barman check nom_cluster doit dans tous les cas être 100% OK avant de rendre la main aux utilisateurs.

Mise à jour : 14/02/2018