{"id":10834,"date":"2018-02-15T15:41:26","date_gmt":"2018-02-15T14:41:26","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/"},"modified":"2023-06-09T16:53:48","modified_gmt":"2023-06-09T14:53:48","slug":"backup-and-restore-postgresql-with-pgbackrest-ii","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/","title":{"rendered":"Backup and Restore PostgreSQL with PgBackRest  II"},"content":{"rendered":"<p><strong>By Mouhamadou Diaw<\/strong><\/p>\n<p>In a precedent <a href=\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-i\/\" target=\"_blank\" rel=\"noopener\">blog<\/a> I shown a basic utilization of <a href=\"http:\/\/pgbackrest.org\/\" target=\"_blank\" rel=\"noopener\">PgBackRest<\/a> which is a tool to backup and restore PostgreSQL databases. In this blog I am going to talk some useful features of this tool. In practical examples we will see some tasks we can do with this tool. Of course the official documentation remains the best source of knowledges.<\/p>\n<p><u>Encryption<\/u><br \/>\nNowadays encryption of backups is very critical and is mandatory for many companies. PgBackRest allows us to encrypt the repository where backups are stored. A passphrase is used to encrypt\/decrypt files of the repository. As you may already know, it is recommended to use a strong passphrase. In the following demonstration we use the openssl to generate a passphrase.<br \/>\n<code><br \/>\n[postgres@pgserver ~]$  openssl rand -base64 48<br \/>\nFhXg7oW2pZb9UICZ4iYZPn3X4I6fF0ni7IL6QjaB1IL8qz4LIrP+GW+XqCZqIi3w<br \/>\n[postgres@pgserver ~]$<br \/>\n<\/code><br \/>\nOnce the passphrase generated, we can update the PgBackRest configuration file with<br \/>\n2 options: repo-cipher-pass and repo-cipher-type<br \/>\n<code><br \/>\n[postgres@pgserver clustpgserver]$ cat \/etc\/pgbackrest.conf<br \/>\n[global]<br \/>\nrepo-path=\/var\/lib\/pgbackrest<br \/>\n<strong>repo-cipher-pass=FhXg7oW2pZb9UICZ4iYZPn3X4I6fF0ni7IL6QjaB1IL8qz4LIrP+GW+XqCZqIi3w<\/strong><br \/>\n<strong>repo-cipher-type=aes-256-cbc<\/strong><br \/>\n[clustpgserver]<br \/>\ndb-path=\/var\/lib\/pgsql\/10\/data<br \/>\nretention-full=2<br \/>\n<\/code><br \/>\nThe next step is to create the stanza<br \/>\n<code><br \/>\n[postgres@pgserver ~]$ pgbackrest --stanza=clustpgserver --log-level-console=info --db-port=5435  stanza-create<br \/>\n2018-02-13 13:54:50.447 P00   INFO: stanza-create command begin 1.28: --db1-path=\/var\/lib\/pgsql\/10\/data --db1-port=5435 --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --stanza=clustpgserver<br \/>\n2018-02-13 13:55:04.520 P00   INFO: stanza-create command end: completed successfully<br \/>\n[postgres@pgserver ~]$<br \/>\n<\/code><br \/>\nAs we can see the system automatically detect that the repository is encrypted and then will rewrite the command including the &#8211;repo-cipher-pass and the &#8211;repo-cipher-type options. After the creation of the stanza we can check the status of our stanza<br \/>\n<code><br \/>\n[postgres@pgserver ~]$ pgbackrest --stanza=clustpgserver --log-level-console=info --db-port=5435  check<br \/>\n2018-02-13 13:56:08.999 P00   INFO: check command begin 1.28: --db1-path=\/var\/lib\/pgsql\/10\/data --db1-port=5435 --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --stanza=clustpgserver<br \/>\n2018-02-13 13:57:08.026 P00   INFO: WAL segment 00000002000000000000004C successfully stored in the archive at '\/var\/lib\/pgbackrest\/archive\/clustpgserver\/10-1\/0000000200000000\/00000002000000000000004C-f5ced60cd351d74a91c9ce2e913b761144165e28.gz'<br \/>\n2018-02-13 13:57:08.030 P00   INFO: check command end: completed successfully<br \/>\n<\/code><br \/>\nEverything seems fine, so let&#8217;s run a backup. Note that outputs are truncated<br \/>\n<code><br \/>\n[postgres@pgserver ~]$ pgbackrest --stanza=clustpgserver --log-level-console=info --db-port=5435 backup<br \/>\n2018-02-13 14:01:40.012 P00   INFO: backup command begin 1.28: --db1-path=\/var\/lib\/pgsql\/10\/data --db1-port=5435 --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --retention-full=2 --stanza=clustpgserver<br \/>\nWARN: no prior backup exists, incr backup has been changed to full<br \/>\n2018-02-13 14:01:54.118 P00   INFO: execute non-exclusive pg_start_backup() with label \"pgBackRest backup started at 2018-02-13 14:01:52\": backup begins after the next regular checkpoint completes<br \/>\n...<br \/>\ntype=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --retention-archive=2 --retention-full=2 --stanza=clustpgserver<br \/>\n2018-02-13 14:35:08.281 P00   INFO: full backup total &lt; 2 - using oldest full backup for 10-1 archive retention<br \/>\n2018-02-13 14:35:08.801 P00   INFO: expire command end: completed successfully<br \/>\n[postgres@pgserver ~]$<br \/>\n<\/code><br \/>\nIn a non-encrypted repository, file backup.info can be read. Now with encryption the if we try to read the file backup.info in the repository, we cannot.<br \/>\n<code><br \/>\n[postgres@pgserver clustpgserver]$ less \/var\/lib\/pgbackrest\/backup\/clustpgserver\/backup.info<br \/>\n\"\/var\/lib\/pgbackrest\/backup\/clustpgserver\/backup.info\" may be a binary file.  See it anyway?<br \/>\n<\/code><br \/>\nAnd using the command strings, we can see that the file is encrypted.<br \/>\n<code><br \/>\n[postgres@pgserver clustpgserver]$ strings \/var\/lib\/pgbackrest\/backup\/clustpgserver\/backup.info<br \/>\nSalted__Fx<br \/>\n.;Ru<br \/>\ncz4@<br \/>\ndo:t<br \/>\npi3\"E<br \/>\nVUSO<br \/>\n}a.R*<br \/>\nWx5M<br \/>\n,?,W<br \/>\n3CXWB<br \/>\n[postgres@pgserver clustpgserver]$<br \/>\n<\/code><br \/>\nFrom now, backups cannot be used unless the password is provided.<\/p>\n<p><u>Restore in another location<\/u><br \/>\nPgBackRest allows to restore to another location. This can be useful if we want to duplicate our cluster on the same server or to another server. In the following demonstration, let\u2019s duplicate on the same server.<br \/>\nThe data directory of the source cluster is \/var\/lib\/pgsql\/10\/data<br \/>\n<code><br \/>\npostgres=# show data_directory;<br \/>\ndata_directory<br \/>\n------------------------<br \/>\n\/var\/lib\/pgsql\/10\/data<br \/>\n(1 row)<br \/>\npostgres=#<br \/>\n<\/code><br \/>\nTo duplicate to a new data directory \/u01\/devdata for example, the option &#8211;db-path is used<br \/>\n<code><br \/>\n[postgres@pgserver log]$ pgbackrest --stanza=clustpgserver --log-level-console=info --db-path=\/u01\/devdata restore<br \/>\n\u2026<br \/>\n\u2026<br \/>\n2018-02-14 09:40:05.755 P01   INFO: restore file \/u01\/devdata\/base\/1\/13657 (0B, 100%)<br \/>\n2018-02-14 09:40:05.773 P01   INFO: restore file \/u01\/devdata\/base\/1\/13652 (0B, 100%)<br \/>\n2018-02-14 09:40:05.811 P01   INFO: restore file \/u01\/devdata\/base\/1\/13647 (0B, 100%)<br \/>\n2018-02-14 09:40:05.983 P01   INFO: restore file \/u01\/devdata\/base\/1\/13642 (0B, 100%)<br \/>\n2018-02-14 09:40:06.067 P00   INFO: write \/u01\/devdata\/recovery.conf<br \/>\n2018-02-14 09:40:14.403 P00   INFO: restore global\/pg_control (performed last to ensure aborted restores cannot be started)<br \/>\n2018-02-14 09:40:30.187 P00   INFO: restore command end: completed successfully<br \/>\n<\/code><br \/>\nAfter the duplicate don\u2019t forget to change the port (as we are in the same server) and then start your new cluster<br \/>\n<code><br \/>\npostgres=# show data_directory ;<br \/>\ndata_directory<br \/>\n----------------<br \/>\n\/u01\/devdata<br \/>\n(1 row)<br \/>\npostgres=#<br \/>\n<\/code><\/p>\n<p><u>Restore specific databases<\/u><br \/>\nWith PgBackRest, we can restore specific user databases. Note that built-in databases (template0, template1 and postgres) are always restored.<br \/>\nLet\u2019s show an example. In our source cluster we actually have two databases test and sandbox.<br \/>\n<code><br \/>\nsandbox=# l<br \/>\nList of databases<br \/>\nName    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges<br \/>\n-----------+----------+----------+-------------+-------------+-----------------------<br \/>\npostgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\nsandbox   | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\ntemplate0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c\/postgres          +<br \/>\n|          |          |             |             | postgres=CTc\/postgres<br \/>\ntemplate1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c\/postgres          +<br \/>\n|          |          |             |             | postgres=CTc\/postgres<br \/>\ntest      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\n(5 rows)<br \/>\n<\/code><br \/>\nIn sandbox we have a table mytab with 2 rows<br \/>\n<code><br \/>\nsandbox=# c sandbox<br \/>\nYou are now connected to database \"sandbox\" as user \"postgres\".<br \/>\nsandbox=# table mytab;<br \/>\nid<br \/>\n----<br \/>\n1<br \/>\n2<br \/>\n(2 rows)<br \/>\n<\/code><br \/>\nNow let\u2019s restore the cluster but only with test database, the option &#8211;db-include will be used.<br \/>\n<code><br \/>\n[postgres@pgserver log]$ pgbackrest --stanza=clustpgserver --log-level-console=info --db-path=\/u01\/devdata --db-include=test restore<br \/>\n2018-02-14 10:11:00.948 P00   INFO: restore command begin 1.28: --db-include=test=1 --db1-path=\/u01\/devdata --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --stanza=clustpgserver<br \/>\n2018-02-14 10:11:05.137 P00   INFO: restore backup set 20180214-095439F_20180214-100446I<br \/>\n2018-02-14 10:11:25.110 P00   INFO: remap $PGDATA directory to \/u01\/devdata<br \/>\n...<br \/>\n<\/code><br \/>\nAfter the restore completed, let\u2019s start the new cluster and let\u2019s verify present databases.<br \/>\n<code><br \/>\n[postgres@pgserver devdata]$ psql -p 5436<br \/>\npsql (10.1)<br \/>\nType \"help\" for help.<br \/>\npostgres=# l<br \/>\nList of databases<br \/>\nName    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges<br \/>\n-----------+----------+----------+-------------+-------------+-----------------------<br \/>\npostgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\nsandbox   | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\ntemplate0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c\/postgres          +<br \/>\n|          |          |             |             | postgres=CTc\/postgres<br \/>\ntemplate1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c\/postgres          +<br \/>\n|          |          |             |             | postgres=CTc\/postgres<br \/>\ntest      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |<br \/>\n(5 rows)<br \/>\n<\/code><br \/>\nWhat!! the sandbox is still present despite the use of option &#8211;include-db=test. But if we try to connect to sandbox database. We get an error.<br \/>\n<code><br \/>\npostgres=# c sandbox<br \/>\nFATAL:  relation mapping file \"base\/24581\/pg_filenode.map\" contains invalid data<br \/>\nPrevious connection kept<br \/>\npostgres=#<br \/>\n<\/code><br \/>\nAnd if we compare at OS level the size of files of the database at the source cluster and at the target<br \/>\n<code><br \/>\n[postgres@pgserver log]$ du -sh \/var\/lib\/pgsql\/10\/data\/base\/24581<br \/>\n7.8M    \/var\/lib\/pgsql\/10\/data\/base\/24581<br \/>\n[postgres@pgserver log]$ du -sh \/u01\/devdata\/base\/24581<br \/>\n16K     \/u01\/devdata\/base\/24581<br \/>\n[postgres@pgserver log]$<br \/>\n<\/code><br \/>\nWe can see that at the target cluster, sandbox uses less disk space during the selective restore than it would have if the entire database had been restored. To finish the selective restore, we have to manually drop the sandbox database. Indeed PgBackRest cannot automatically drop the database because the cluster is not accessible until the recovery process finishes.<br \/>\n<code><br \/>\npostgres=# drop database sandbox;<br \/>\nDROP DATABASE<br \/>\npostgres=#<br \/>\n<\/code><\/p>\n<p><u>Automatic cleanup of expired backups<\/u><br \/>\nAnother nice feature of PgBackRest is that expired backups are automatically removed.<br \/>\nIf we check our pgbackrest.conf file, we see that the retention-full is set to 2. This means that 2 full backups will be maintained. So if we do a third full backup, the first full backup and all corresponding incremental and differential backups will be expired and removed<br \/>\n<code><br \/>\n[postgres@pgserver log]$ cat \/etc\/pgbackrest.conf<br \/>\n[global]<br \/>\nrepo-path=\/var\/lib\/pgbackrest<br \/>\nrepo-cipher-pass=FhXg7oW2pZb9UICZ4iYZPn3X4I6fF0ni7IL6QjaB1IL8qz4LIrP+GW+XqCZqIi3w<br \/>\nrepo-cipher-type=aes-256-cbc<br \/>\n[clustpgserver]<br \/>\ndb-path=\/var\/lib\/pgsql\/10\/data<br \/>\nretention-full=2<br \/>\n[postgres@pgserver log]$<br \/>\n<\/code><br \/>\nLet\u2019s do a quick demonstration. Actually we have 2 full backups<br \/>\n<code><br \/>\n[postgres@pgserver log]$ pgbackrest --stanza=clustpgserver info<br \/>\nstanza: clustpgserver<br \/>\nstatus: ok<br \/>\ndb (current)<br \/>\nwal archive min\/max (10-1): 00000002000000000000004E \/ 000000020000000000000056<br \/>\nfull backup: 20180213-140152F<br \/>\ntimestamp start\/stop: 2018-02-13 14:01:52 \/ 2018-02-13 14:32:00<br \/>\nwal start\/stop: 00000002000000000000004E \/ 00000002000000000000004E<br \/>\ndatabase size: 577MB, backup size: 577MB<br \/>\nrepository size: 28.8MB, repository backup size: 28.8MB<br \/>\nincr backup: 20180213-140152F_20180213-152509I<br \/>\ntimestamp start\/stop: 2018-02-14 09:31:03 \/ 2018-02-14 09:33:17<br \/>\nwal start\/stop: 000000020000000000000052 \/ 000000020000000000000052<br \/>\ndatabase size: 30.7MB, backup size: 285.3KB<br \/>\nrepository size: 3.6MB, repository backup size: 24.3KB<br \/>\nbackup reference list: 20180213-140152F<br \/>\nfull backup: 20180214-095439F<br \/>\ntimestamp start\/stop: 2018-02-14 09:54:39 \/ 2018-02-14 09:58:53<br \/>\nwal start\/stop: 000000020000000000000054 \/ 000000020000000000000054<br \/>\ndatabase size: 30.7MB, backup size: 30.7MB<br \/>\nrepository size: 3.6MB, repository backup size: 3.6MB<br \/>\nincr backup: 20180214-095439F_20180214-100446I<br \/>\ntimestamp start\/stop: 2018-02-14 10:04:46 \/ 2018-02-14 10:07:43<br \/>\nwal start\/stop: 000000020000000000000056 \/ 000000020000000000000056<br \/>\ndatabase size: 38.3MB, backup size: 7.6MB<br \/>\nrepository size: 4.5MB, repository backup size: 928.5KB<br \/>\nbackup reference list: 20180214-095439F<br \/>\n[postgres@pgserver log]$<br \/>\n<\/code><br \/>\nAnd we can confirm by executing a simple ls in the repository where backups are stored<br \/>\n<code><br \/>\n[postgres@pgserver clustpgserver]$ ls -ld *<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 13 14:32 20180213-140152F<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 14 09:33 20180213-140152F_20180213-152509I<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 14 09:59 20180214-095439F<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 14 10:07 20180214-095439F_20180214-100446I<br \/>\ndrwxr-x---. 3 postgres postgres   17 Feb 13 14:33 backup.history<br \/>\n-rw-r-----. 1 postgres postgres 2992 Feb 14 10:08 backup.info<br \/>\n-rw-r-----. 1 postgres postgres 2992 Feb 14 10:08 backup.info.copy<br \/>\nlrwxrwxrwx. 1 postgres postgres   33 Feb 14 10:08 latest -&gt; 20180214-095439F_20180214-100446I<br \/>\n[postgres@pgserver clustpgserver]$ ls -ld<br \/>\ndrwxr-x---. 7 postgres postgres 4096 Feb 14 10:08 .<br \/>\n[postgres@pgserver clustpgserver]$ ls -ld *<br \/>\n<\/code><br \/>\nNow let\u2019s do a third full backup<br \/>\n<code><br \/>\n[postgres@pgserver clustpgserver]$ pgbackrest --stanza=clustpgserver --log-level-console=info  --db-port=5435 --type=full backup<br \/>\n2018-02-14 10:55:52.250 P00   INFO: backup command begin 1.28: --db1-path=\/var\/lib\/pgsql\/10\/data --db1-port=5435 --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --retention-full=2 --stanza=clustpgserver --type=full<br \/>\n\u2026<br \/>\n2018-02-14 11:19:02.001 P00   INFO: backup command end: completed successfully<br \/>\n2018-02-14 11:19:02.107 P00   INFO: expire command begin 1.28: --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --retention-archive=2 --retention-full=2 --stanza=clustpgserver<br \/>\n<strong>2018-02-14 11:19:02.928 P00   INFO: expire full backup set: 20180213-140152F, 20180213-140152F_20180213-152509I<br \/>\n2018-02-14 11:22:08.759 P00   INFO: remove expired backup 20180213-140152F_20180213-152509I<br \/>\n2018-02-14 11:22:09.000 P00   INFO: remove expired backup 20180213-140152F<\/strong><br \/>\n2018-02-14 11:22:49.387 P00   INFO: expire command end: completed successfully<br \/>\n[postgres@pgserver clustpgserver]$<br \/>\n<\/code><br \/>\nWe can see that at the end of backups, some old backups are expired and removed. We can also confirm this by listing files in the repository<br \/>\n<code><br \/>\n[postgres@pgserver clustpgserver]$ ls -ld *<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 14 09:59 20180214-095439F<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 14 10:07 20180214-095439F_20180214-100446I<br \/>\ndrwxr-x---. 3 postgres postgres   69 Feb 14 11:13 20180214-105603F<br \/>\ndrwxr-x---. 3 postgres postgres   17 Feb 13 14:33 backup.history<br \/>\n-rw-r-----. 1 postgres postgres 2320 Feb 14 11:19 backup.info<br \/>\n-rw-r-----. 1 postgres postgres 2320 Feb 14 11:20 backup.info.copy<br \/>\nlrwxrwxrwx. 1 postgres postgres   16 Feb 14 11:14 latest -&gt; 20180214-105603F<br \/>\n[postgres@pgserver clustpgserver]$<br \/>\n<\/code><\/p>\n<p><u>Point-in-Time Recovery<\/u><br \/>\nPgBackRest can also do a point-in-time recovery. Let\u2019s drop table article in the database test<br \/>\n<code><br \/>\ntest=# table article;<br \/>\nnom<br \/>\n---------<br \/>\nprinter<br \/>\n(1 row)<br \/>\n.<br \/>\ntest=# select now();<br \/>\nnow<br \/>\n-------------------------------<br \/>\n2018-02-14 11:39:28.024378+01<br \/>\n(1 row)<br \/>\n.<br \/>\ntest=# drop table article;<br \/>\nDROP TABLE<br \/>\n.<br \/>\ntest=# table article;<br \/>\nERROR:  relation \"article\" does not exist<br \/>\nLINE 1: table article;<br \/>\n^<br \/>\ntest=#<br \/>\n<\/code><br \/>\nAnd now let\u2019s restore until just before we drop the table let\u2019s say 2018-02-14 11:39:28.<br \/>\nBut as we have many backup sets we have to restore from a backup done before the table was dropped.<br \/>\nIf we check our backups, we have to restore from the full backup: 20180214-105603F<br \/>\nwhich was taken before table article was dropped.<br \/>\n<code><br \/>\n[postgres@pgserver devdata]$ pgbackrest --stanza=clustpgserver --log-level-console=info info<br \/>\nstanza: clustpgserver<br \/>\nstatus: ok<br \/>\ndb (current)<br \/>\nwal archive min\/max (10-1): 000000020000000000000054 \/ 00000002000000000000005A<br \/>\nfull backup: 20180214-095439F<br \/>\ntimestamp start\/stop: 2018-02-14 09:54:39 \/ 2018-02-14 09:58:53<br \/>\nwal start\/stop: 000000020000000000000054 \/ 000000020000000000000054<br \/>\ndatabase size: 30.7MB, backup size: 30.7MB<br \/>\nrepository size: 3.6MB, repository backup size: 3.6MB<br \/>\nincr backup: 20180214-095439F_20180214-100446I<br \/>\ntimestamp start\/stop: 2018-02-14 10:04:46 \/ 2018-02-14 10:07:43<br \/>\nwal start\/stop: 000000020000000000000056 \/ 000000020000000000000056<br \/>\ndatabase size: 38.3MB, backup size: 7.6MB<br \/>\nrepository size: 4.5MB, repository backup size: 928.5KB<br \/>\nbackup reference list: 20180214-095439F<br \/>\n<strong> full backup: 20180214-105603F<br \/>\ntimestamp start\/stop: 2018-02-14 10:56:03 \/ 2018-02-14 11:12:26<\/strong><br \/>\nwal start\/stop: 000000020000000000000058 \/ 000000020000000000000058<br \/>\ndatabase size: 38.3MB, backup size: 38.3MB<br \/>\nrepository size: 4.5MB, repository backup size: 4.5MB<br \/>\nincr backup: 20180214-105603F_20180214-121044I<br \/>\ntimestamp start\/stop: 2018-02-14 12:10:44 \/ 2018-02-14 12:15:14<br \/>\nwal start\/stop: 00000002000000000000005A \/ 00000002000000000000005A<br \/>\ndatabase size: 38.3MB, backup size: 1.1MB<br \/>\nrepository size: 4.5MB, repository backup size: 140.8KB<br \/>\nbackup reference list: 20180214-105603F<br \/>\n[postgres@pgserver devdata]$<br \/>\n<\/code><br \/>\nFor the restore we use the option &#8211;set which allows us to specify the backup set we want to use for the restore. Note also the use of &#8211;type=time and &#8211;target<br \/>\n<code><br \/>\n[postgres@pgserver log]$ pgbackrest --stanza=clustpgserver --log-level-console=info   --type=time  \"--target=2018-02-14 11:39:28.024378+01\" --db-path=\/u01\/devdata  --set=20180214-105603F  restore<br \/>\n2018-02-14 13:36:50.848 P00   INFO: restore command begin 1.28: --db1-path=\/u01\/devdata --log-level-console=info --repo-cipher-pass= --repo-cipher-type=aes-256-cbc --repo-path=\/var\/lib\/pgbackrest --set=20180214-105603F --stanza=clustpgserver \"--target=2018-02-14 11:39:28.024378+01\" --type=time<br \/>\n2018-02-14 13:37:03.406 P00   INFO: restore backup set 20180214-105603F<br \/>\n...<br \/>\n<\/code><br \/>\nAt the end of the restore let\u2019s see the contents of the recovery.done file<br \/>\n<code><br \/>\n[postgres@pgserver devdata]$ cat recovery.conf<br \/>\nrestore_command = '\/usr\/bin\/pgbackrest --db1-path=\/u01\/devdata --log-level-console=info --stanza=clustpgserver archive-get %f \"%p\"'<br \/>\nrecovery_target_time = '2018-02-14 11:39<br \/>\n<\/code><br \/>\nIf we start our new cluster, we can see in log files that PITR is starting<br \/>\n<code>2018-02-14 13:54:23.824 CET [10049] LOG:  starting point-in-time recovery to 2018-02-14 11:39:28.024378+01<\/code><br \/>\nAnd once the recovery finished, we can verify that the table article is present<br \/>\n<code><br \/>\npostgres=# c test<br \/>\nYou are now connected to database \"test\" as user \"postgres\".<br \/>\ntest=# d article<br \/>\nTable \"public.article\"<br \/>\nColumn |         Type          | Collation | Nullable | Default<br \/>\n--------+-----------------------+-----------+----------+---------<br \/>\nnom    | character varying(50) |           |          |<br \/>\n.<br \/>\ntest=# table article;<br \/>\nnom<br \/>\n---------<br \/>\nprinter<br \/>\n(1 row)<br \/>\ntest=#<br \/>\n<\/code><br \/>\n<strong>Conclusion: <\/strong><br \/>\nIn this blog I talked about some features about PgBackRest. But as already specified, there are many, many other options with this wonderful tool. The official documentation can give more information. In future blogs we will explore more with advanced configuration.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>By Mouhamadou Diaw In a precedent blog I shown a basic utilization of PgBackRest which is a tool to backup and restore PostgreSQL databases. In this blog I am going to talk some useful features of this tool. In practical examples we will see some tasks we can do with this tool. Of course the [&hellip;]<\/p>\n","protected":false},"author":27,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229],"tags":[1293,77],"type_dbi":[],"class_list":["post-10834","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","tag-pgbackrest","tag-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Backup and Restore PostgreSQL with PgBackRest II - dbi Blog<\/title>\n<meta name=\"description\" content=\"PostgreSQL, Backup and restore, PgBackRest\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Backup and Restore PostgreSQL with PgBackRest II\" \/>\n<meta property=\"og:description\" content=\"PostgreSQL, Backup and restore, PgBackRest\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-15T14:41:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-09T14:53:48+00:00\" \/>\n<meta name=\"author\" content=\"Oracle Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Oracle Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\"},\"author\":{\"name\":\"Oracle Team\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee\"},\"headline\":\"Backup and Restore PostgreSQL with PgBackRest II\",\"datePublished\":\"2018-02-15T14:41:26+00:00\",\"dateModified\":\"2023-06-09T14:53:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\"},\"wordCount\":865,\"commentCount\":0,\"keywords\":[\"pgbackrest\",\"PostgreSQL\"],\"articleSection\":[\"Database Administration &amp; Monitoring\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\",\"name\":\"Backup and Restore PostgreSQL with PgBackRest II - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2018-02-15T14:41:26+00:00\",\"dateModified\":\"2023-06-09T14:53:48+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee\"},\"description\":\"PostgreSQL, Backup and restore, PgBackRest\",\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Backup and Restore PostgreSQL with PgBackRest II\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee\",\"name\":\"Oracle Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g\",\"caption\":\"Oracle Team\"},\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/oracle-team\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Backup and Restore PostgreSQL with PgBackRest II - dbi Blog","description":"PostgreSQL, Backup and restore, PgBackRest","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/","og_locale":"en_US","og_type":"article","og_title":"Backup and Restore PostgreSQL with PgBackRest II","og_description":"PostgreSQL, Backup and restore, PgBackRest","og_url":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/","og_site_name":"dbi Blog","article_published_time":"2018-02-15T14:41:26+00:00","article_modified_time":"2023-06-09T14:53:48+00:00","author":"Oracle Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Oracle Team","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/"},"author":{"name":"Oracle Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee"},"headline":"Backup and Restore PostgreSQL with PgBackRest II","datePublished":"2018-02-15T14:41:26+00:00","dateModified":"2023-06-09T14:53:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/"},"wordCount":865,"commentCount":0,"keywords":["pgbackrest","PostgreSQL"],"articleSection":["Database Administration &amp; Monitoring"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/","url":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/","name":"Backup and Restore PostgreSQL with PgBackRest II - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2018-02-15T14:41:26+00:00","dateModified":"2023-06-09T14:53:48+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee"},"description":"PostgreSQL, Backup and restore, PgBackRest","breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/backup-and-restore-postgresql-with-pgbackrest-ii\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Backup and Restore PostgreSQL with PgBackRest II"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee","name":"Oracle Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g","caption":"Oracle Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/oracle-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/10834","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/27"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=10834"}],"version-history":[{"count":1,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/10834\/revisions"}],"predecessor-version":[{"id":25763,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/10834\/revisions\/25763"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=10834"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=10834"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=10834"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=10834"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}