Backup and Recovery Methods Overview
Backup is the foundation of a DBA’s livelihood. With backups, there’s no need to panic.
There are three forms of backup: SQL dumps, file system backups, and continuous archiving.
1. SQL Dumps
The idea behind the SQL dump method is:
Create a file composed of SQL commands that the server can use to rebuild a database in the same state as when the dump was made.
1.1 Dumping
The tools pg_dump and pg_dumpall are used for SQL dumps. Results are output to stdout.
pg_dumpis a regular PostgreSQL client application. Backup work can be done from any remote host that can access the database.pg_dumpdoesn’t run with any special privileges and must have read access to the tables you want to back up, following the same HBA mechanisms.- To back up an entire database, you almost always need database superuser privileges.
- The important advantage of this backup method is that it’s cross-version and cross-machine architecture compatible. (Can trace back to version 7.0)
pg_dumpbackups are internally consistent, representing a database snapshot at the moment the dump started. Updates during the dump are not included.pg_dumpdoesn’t block other database operations, except for commands requiring exclusive locks (like most ALTER TABLE commands).
1.2 Restoring
Text dump files can be read by psql. The common command to restore from a dump is:
This command doesn’t create the database
dbname; you must create it fromtemplate0before running psql. For example, use the commandcreatedb -T template0 dbname. By default,template1andtemplate0are the same, and newly created databases default to usingtemplate1as a template.CREATE DATABASE dbname TEMPLATE template0;Non-text file dumps can be restored using the pg_restore tool.
Before starting restoration, object owners in the dump and users who have been granted privileges must already exist. If they don’t exist, the restoration process won’t be able to create objects with original ownership and privileges (sometimes this is what you need, but usually not).
If restoration stops on errors, you can set the
ON_ERROR_STOPvariable to run psql, which exits with status 3 on SQL errors:
- During restoration, you can use a single transaction to ensure either complete correct restoration or complete rollback. Use
-1or--single-transaction - pg_dump and psql can do on-the-fly dumping and restoration through pipes
1.3 Global Dumps
Some information belongs to the database cluster rather than individual databases, such as roles and tablespaces. If you want to dump these, use pg_dumpall
If you only want global data (roles and tablespaces), you can use the -g, --globals-only parameter.
The dump results can be restored using psql. Usually, loading the dump into an empty cluster can use postgres as the database name:
- Restoring a pg_dumpall dump often requires database superuser access privileges because it needs to restore role and tablespace information.
- If you used tablespaces, make sure the tablespace paths in the dump are appropriate for the new installation.
- pg_dumpall works by first creating role and tablespace dumps, then doing pg_dump for each database. This means each database is internally consistent, but snapshots of different databases are not synchronized.
1.4 Command Practice
Prepare environment, create test database:
2. File System Dumps
The idea behind the file system dump method is: copy all files in the data directory. To get a usable backup, all backup files should remain consistent.
So usually, and to get a usable backup, all backup files should remain consistent.
- File system copying doesn’t do logical parsing, just simple file copying. The advantage is fast execution, saving logical parsing and index rebuilding time. The disadvantage is larger space usage and can only be used for backing up entire database clusters.
Simplest way: shut down, directly copy all files in the data directory.
There are ways to get consistent frozen snapshots through file systems (like xfs) without shutting down, but WAL and data directories must be consistent.
You can make pg_basebackup for remote archive backup without shutting down.
You can use rsync to incrementally sync data changes to remote locations during shutdown.
3. PITR Continuous Archiving and Point-in-Time Recovery
PostgreSQL continuously generates WAL during operation. WAL records operation logs. Starting from a baseline full backup and replaying subsequent WAL can restore the database to any point in time. To implement this functionality, you need to configure WAL archiving to continuously save the WAL generated by the database.
WAL is logically an infinite byte stream. The pg_lsn type (bigint) can mark positions in WAL. pg_lsn represents a byte position offset in WAL. But in practice, WAL isn’t a continuous single file but is segmented into 16MB chunks.
WAL file names follow a pattern and cannot be changed during archiving. Usually 24 hexadecimal digits, like 000000010000000000000003, where the first 8 hex digits represent the timeline, and the last 16 digits represent the 16MB block sequence number, i.e., the value of lsn >> 24.
When viewing pg_lsn, for example 0/84A8300, just remove the last six hex digits to get the latter part of the WAL file sequence number. Here, that’s 8. If using the default timeline 1, the corresponding WAL file is 000000010000000000000008.
3.1 Environment Preparation
3.2 Configure Automatic Archiving Command
Archive scripts can be as simple as just a cp, or very complex. But note the following:
Archive commands execute under database user
postgres, best placed in a 0700 directory.Archive commands should refuse to overwrite existing files, returning an error code when overwriting occurs.
Archive commands can be updated by reloading configuration.
Handle archive failure situations
Archive files should retain original file names.
WAL doesn’t record configuration file changes.
In archive commands:
%pis replaced with the path of the WAL to be archived, and%fis replaced with the filename of the WAL to be archivedArchive scripts can use more complex logic, for example the following archive command creates a folder named with date YYYYMMDD in the archive directory each day, removes the previous day’s archive logs at 12 noon daily. Each day’s archive logs are stored compressed with xz.
Archiving can also be done using external dedicated backup tools, such as
pgbackrestandbarman.
3.3 Test Archiving
Start a monitoring loop in the current shell, continuously querying WAL position and file changes in archive directory and pg_wal:
In another shell, create a test table foobar with a single timestamp column and introduce load, writing 10,000 records per second:
Natural WAL Switching
You can see that when the WAL LSN position exceeds 16M (representable by the last 6 hex digits), it rotates to a new WAL file, and the archive command archives the completed WAL.
Manual WAL Switching
Open another shell and execute pg_switch_wal to force writing a new WAL file:
You can see that although the position was only at 32C1D68, it immediately jumped to the next 16MB boundary.
Force Kill Database
When the database shuts down abnormally due to failure, after restart, it will replay WAL starting from the most recent checkpoint, which is 0/2FB0160.
At this point, WAL archiving has been confirmed to work normally.
3.4 Create Base Backup
First, check the current WAL position:
Use pg_basebackup to create a base backup:
When creating a base backup, a checkpoint is immediately created to ensure all dirty data pages are flushed to disk.
3.5 Using Backups
Direct Use
The simplest way to use it is to start it directly with pg_ctl.
When recovery.conf doesn’t exist, doing this starts a new complete database instance, preserving exactly the state when the backup was completed. The database won’t realize it’s a backup but thinks it didn’t shut down properly last time and should apply WAL in the pg_wal directory for recovery, then restart normally.
Basic full backups might be made daily or weekly. To restore to the latest moment, you need to use them with WAL archiving.
Using WAL Archives to Catch Up
You can create a recovery.conf file in the backup database and specify the restore_command option. This way, when you start this data directory with pg_ctl, postgres will sequentially fetch the required WAL until there are no more.
Continue executing load on the original master. At this time, WAL progress has reached 0/9060CE0, while the backup position was still at 0/5000028 when it was made.
After starting the backup, you can see that the backup database automatically fetched WAL files 5-8 from the archive folder and applied them.
But using WAL archives for recovery also has problems. For example, querying the latest data records from the master and standby, you find a one-second time difference. This means that WAL not yet written by the master hasn’t been archived and thus wasn’t applied.
Usually archive_command, restore_command are mainly used for emergency recovery, such as when both master and standby are down.
3.6 Specifying Progress
By default, recovery will continue to the end of the WAL log. The following parameters can be used to specify an earlier stopping point. At most one of the four options recovery_target, recovery_target_name, recovery_target_time, and recovery_target_xid can be used. If multiple are used in the configuration file, the last one will be used.
Among the four recovery targets above, recovery_target_time is commonly used to specify what time to restore the system to.
Several other commonly used options include:
recovery_target_inclusive(boolean): Whether to include the target point, default is truerecovery_target_timeline(string): Specify recovery to a specific timeline.recovery_target_action(enum): Specify the action the server should take immediately upon reaching the recovery target.pause: Pause recovery, default option, can be resumed withpg_wal_replay_resume.shutdown: Automatically shut down.promote: Start accepting connections
For example, a backup was created at 2018-01-25 18:51:20:
After running for two minutes, at 2018-01-25 18:53:05 we found some dirty data, so we recover from backup, hoping to restore to the state one minute before the dirty data appeared, for example 2018-01-25 18:52
You can configure like this:
When the new database instance completes recovery, you can see its state has indeed returned to 18:52, which is exactly what we expected.
3.7 Timelines
Whenever archive recovery is complete, that is, when the server can start accepting new queries and writing new WAL, a new timeline is created to distinguish newly generated WAL records. WAL file names consist of timeline and log sequence numbers, so new timeline WAL won’t overwrite old timeline WAL. Timelines are mainly used to resolve complex recovery operation conflicts. For example, imagine a scenario: after restoring to 18:52 just now, the new server starts continuously accepting requests:
You can see that two WAL segment files numbered 6 appeared in the WAL archive directory. Without the timeline prefix for distinction, WAL would be overwritten.
If you regret after completing recovery, you can use the base backup to recover again to the state when first run to 18:53 by specifying recovery_target_timeline = '1'.
3.8 Other Considerations
- Before PostgreSQL 10, operations on hash indexes weren’t recorded in WAL and needed manual REINDEX on slaves.
- Don’t modify any template databases while creating base backups
- Note that tablespaces strictly record their paths literally. If you used tablespaces, be very careful during recovery.
4. Creating Standby Servers
Through master-slave setups, you can simultaneously improve availability and reliability.
- Master-slave read-write separation improves performance: write requests go to master, transmitted to standby through WAL streaming replication, standby accepts read requests.
- Improve reliability through backups: when one server fails, another can immediately take over (promote slave or make new slave)
Usually master-slave, replica, standby belong to high availability topics. But from another perspective, standby is also a form of backup.
Create Directories
Create Master
Create User
Creating a standby requires a user with REPLICATION privileges. Here we create a replication user in the master:
To create a standby, you need a user with REPLICATION privileges and allow access in pg_hba. Version 10 allows by default:
Create Standby
Create a slave instance through pg_basebackup. Actually connects to the master instance and copies a data directory locally.
The key here is the -R option, which automatically fills master connection information into recovery.conf during backup creation. This way, when starting with pg_ctl, the database realizes it’s a standby and automatically fetches WAL from the master to catch up.
Start Standby
The only difference between standby and master is an additional recovery.conf file in the data directory. This file not only identifies standby status but is also needed during failure recovery. For standbys created by pg_basebackup, it contains two parameters by default:
standby_mode specifies whether to start PostgreSQL as a standby.
During backup, standby_mode is off by default. This way, when all WAL is fetched, recovery completes and enters normal working mode.
If turned on, the database realizes it’s a standby, so even when reaching the end of WAL, it won’t stop but will continue fetching WAL from the master, catching up with the master’s progress.
There are two ways to fetch WAL: through primary_conninfo streaming replication (new feature after 9.0, recommended, default), or through restore_command to manually specify WAL acquisition method (old method, used for recovery).
Check Status
All standbys of the master can be viewed through the system view pg_stat_replication:
Check master and standby status using function pg_is_in_recovery. Standby will be in recovery state:
Create table in master, standby can also see it:
Insert data in master, standby can also see it:
Now master-standby is configured and ready.
