Restauration, PITR dans une timeline précédente avec Barman

Inutile de compliquer les choses

      Avec PostgreSQL, les informations de journalisation correspondant aux transactions sont enregistrées dans des fichiers WAL (write ahead log). Ces WAL sont produits et archivés au fil du temps et appartiennent donc à une timeline, une ligne de temps.
      La séquence de WAL pourrait se poursuivre indéfiniment dans la même timeline mais il est parfois nécessaire de faire revenir le cluster en arrière pour annuler des transactions erronées ou encore une corruption. La restauration est alors un PITR (point in time recovery).
      Après un PITR, une nouvelle timeline (incarnation dans le vocabulaire Oracle Database) est créée.
      Les timelines sont souvent décrites avec du vocabulaire de science-fiction. J'aime beaucoup le Maître des Montagnes ou la Fin de l'Eternité mais nous allons ici simplifier les choses. Il est en effet douteux que vous vous intéressiez aux paradoxes spatio-temporels en situation de crise.
      Pour UN cluster donné, chaque transaction a été validée à UN timestamp et enregistrée dans UN fichier WAL qui appartient à UNE timeline. Une timeline peut ainsi être vue comme un ensemble de fichiers WAL produits dans un intervalle de temps. Il n'y aucun chevauchement possible.
      Les PITR non planifiés sont la plupart du temps effectués en fonction d'un timestamp et avoir plusieurs timelines ne complique pas les choses. Si vous avez suivi le conseil que je donne dans cette page consacrée au PITR alors vous disposez d'au moins un backup de base effectué au début de chaque timeline avant toute activité transactionnelle significative.
      Nous allons supposer que nous disposons d'une sauvegarde Barman 2.x distante pour notre environnement PostgreSQL 10 sur Debian 10 et que voulons réaliser un PITR au 18/02/2018 20:00:00 :

-- serveur bapr, barman cd /var/lib/barman/apptra001/wals ls -ltR ./0000000500000000: total 348 -rw------- 1 barman barman 56583 févr. 18 22:17 000000050000000000000018 ... -rw------- 1 barman barman 77418 févr. 18 21:37 000000050000000000000013 ./0000000400000000: total 316 -rw------- 1 barman barman 64728 févr. 18 20:51 000000040000000000000017 ... -rw------- 1 barman barman 95205 févr. 18 20:15 000000040000000000000013 ./0000000300000000: total 364 -rw------- 1 barman barman 46445 févr. 18 20:10 000000030000000000000014 ... -rw------- 1 barman barman 94531 févr. 18 19:20 000000030000000000000010 ./0000000200000000: total 104 -rw------- 1 barman barman 27252 févr. 18 19:16 000000020000000000000013 ... -rw------- 1 barman barman 44614 févr. 18 18:56 000000020000000000000011 ./0000000100000000: total 932 -rw------- 1 barman barman 60268 févr. 18 18:47 000000010000000000000011 ... -rw------- 1 barman barman 27129 févr. 18 16:47 000000010000000000000005 barman list-backup apptra001 apptra001 20180218T213849 - Sun Feb 18 21:38:51 2018 - Size: 23.1 MiB - WAL Size: 197.9 KiB apptra001 20180218T201542 - Sun Feb 18 20:15:46 2018 - Size: 23.1 MiB - WAL Size: 185.4 KiB apptra001 20180218T192046 - Sun Feb 18 19:20:52 2018 - Size: 23.0 MiB - WAL Size: 232.5 KiB apptra001 20180218T185648 - Sun Feb 18 18:56:52 2018 - Size: 23.0 MiB - WAL Size: 26.6 KiB apptra001 20180218T164738 - Sun Feb 18 16:47:41 2018 - Size: 22.7 MiB - WAL Size: 875.9 KiB barman show-backup apptra001 20180218T192046 Backup 20180218T192046: .... Timeline : 3 ....


      Notre "ls" n'est pas très précis , d'autant plus que les fichiers WAL ne sont pas archivés instantanément dans Barman, mais c'est suffisant pour affirmer que la timeline à considérer n'est pas la timeline courante, 5, mais la 3. Le dossier correspondant à la timeline 3 comprend des fichiers WAL produits entre le 18/02/2018 19:20 et le 18/02/2018 20:10.
      Le backup à considérer est ici 20180218T192046 effectué au cours de la timeline 3 comme le confirment un barman show-backup ou un barman diagnose.
      A présent place au PITR :

-- serveur pgpr10, root pg_ctlcluster 10 apptra001 stop rm -fr /var/lib/postgresql/10/apptra001/* -- serveur bapr, barman barman recover --target-time "2018-02-18 20:00:00" --remote-ssh-command "ssh postgres@pgpr10" apptra001 20180218T192046 /var/lib/postgresql/10/apptra00 ... Your PostgreSQL server has been successfully prepared for recovery! -- serveur pgpr10, root pg_ctlcluster 10 apptra001 start tail -f /var/log/postgresql/postgresql-10-apptra001.log ... 2018-02-18 22:49:02.025 CET [2695] LOG: arrêt de la restauration avant validation de la transaction 8287, 2018-02-18 20:00:01.725972+01 2018-02-18 22:49:02.025 CET [2695] LOG: restauration en pause 2018-02-18 22:49:02.025 CET [2695] ASTUCE : Exécuter pg_wal_replay_resume() pour continuer. -- serveur pgpr10, postgres psql select max(c1) from temoin; max --------------------------- 2018-02-18 19:59:59.93382 (1 ligne) select pg_wal_replay_resume(); pg_wal_replay_resume ---------------------- (1 ligne) -- serveur pgpr10, root mv /var/lib/postgresql/10/apptra001/postgresql.auto.conf.origin /var/lib/postgresql/10/apptra001/postgresql.auto.conf pg_ctlcluster 10 apptra001 reload -- serveur bapr, barman barman receive-wal --create-slot apptra001 Creating physical replication slot 'barman' on server 'apptra001' Replication slot 'barman' created barman receive-wal --reset apptra001 Starting receive-wal for server apptra001 Resetting receive-wal directory status Removing status file /var/lib/barman/apptra001/streaming/00000005000000000000001C.partial barman cron Starting WAL archiving for server apptra001 Starting streaming archiver for server apptra001 barman check apptra001 ...OK barman backup apptra001


      L'existence de plusieurs timelines n'a pas changé la manière d'effectuer notre PITR qui a donné le résultat escompté. En situation réelle, je conseille d'effectuer le PITR vers un serveur et un stockage différents de ceux du cluster de production afin d'éviter le suraccident, d'effectuer des comparaisons etc.
      Le recover opère par défaut sur la timeline dans laquelle a été effectuée le backup de base. C'est pourquoi je recommande d'effectuer un premier backup au début de chaque timeline. PostgreSQL est capable de traverser les timelines comme Oracle Database est capable depuis la version 10g de traverser les incarnations donc il serait malgré tout possible de s'en passer, cela fait l'objet de cette page.

Mise à jour : 18/02/2018