Commit 11b73982 authored by Marco Nenciarini's avatar Marco Nenciarini

Update upstream source from tag 'upstream/2.5'

Update to upstream version '2.5'
with Debian dir cdea6942b629e7e22635aab134015406c7566508
parents 9a263202 75ab655c
2018-10-22 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Update the ChangeLog file
Set version to 2.5
2018-10-17 Leonardo Cecchi <leonardo.cecchi@2ndquadrant.com>
Avoid checking failed backups
If a backup is in a different state than WAITING_FOR_WALS, we don't need
to check it for consistency.
2018-10-17 Gabriele Bartolini <gabriele.bartolini@2ndQuadrant.it>
Prepared release notes for 2.5 with tentative release date
2018-10-16 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Avoid being verbose about missing WAL files in `check-backup`
The number of missing WAL files can be huge, and storing such list or
displaying it in the error message is consuming and not useful.
The check now stops as soon as it finds a missing file, and the message
has changed to display only that file.
2018-10-15 Leonardo Cecchi <leonardo.cecchi@2ndquadrant.com>
Support switch-wal on standby server
The switch-wal command can also be used on standby servers, but only for
the `--archive` option.
Use XLOG segment size in check_backup
The `check_backup` command wasn't using the current XLOG segment size to
generate the WAL file names.
2018-10-15 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Implement atomic BackupInfo writes
2018-10-15 Leonardo Cecchi <leonardo.cecchi@2ndquadrant.com>
Notify users when attempting to recover a WAITING_FOR_WALS backup
When a backup which is still in WAITING_FOR_WALS state will be
recovered, a warning message will be raised if the get-wal feature
is not in use.
Another warning message will be raised if the backup is still in the
same state after having copied the data files.
2018-10-15 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Always update the backup status during `check-backup` execution
This change aims to detect cases where the content of the WAL archive
has been modified outside Barman.
2018-10-15 Gabriele Bartolini <gabriele.bartolini@2ndQuadrant.it>
Cover WAL streaming in documentation for backup from a standby
2018-10-14 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
In PostgreSQL 11 `wal_segment_size` is returned in bytes
2018-10-04 Leonardo Cecchi <leonardo.cecchi@2ndquadrant.com>
Add `check-backup` command
Make sure that all the required WAL files to check the consistency
of a physical backup (that is, from the beginning to the end of
the full backup, as outlined in the backup label) are correctly archived.
This command is automatically invoked by the `cron` command,
and at the end of every backup operation.
2018-10-09 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Set version to 2.5a1
2018-09-14 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Pin py<1.6.0 to keep 2.6 support
2018-08-02 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Fix decoding errors reading external commands output
Completed the fix started in commit f14e405e9b36de912899d0735563eed76f479164
The StreamLineProcessor implementation is enough to ensure that
the Command out and err property are proper unicode strings or None
Closes: #174
Pin pytest-timeout<1.2.1 to continue supporting Python 2.6
2018-05-23 Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
Update the ChangeLog file
......
Barman News - History of user-visible changes
Copyright (C) 2011-2018 2ndQuadrant Limited
Version 2.5 - 23 Oct 2018
- Add support for PostgreSQL 11
- Add check-backup command to verify that WAL files required for
consistency of a base backup are present in the archive. Barman now
adds a new state (WAITING_FOR_WALS) after completing a base backup,
and sets it to DONE once it has verified that all WAL files from
start to the end of the backup exist. This command is included in
the regular cron maintenance job. Barman now notifies users
attempting to recover a backup that is in WAITING_FOR_WALS state.
- Allow switch-xlog --archive to work on a standby (just for the
archive part)
- Bug fixes:
- Fix decoding errors reading external commands output (issue
#174)
- Fix documentation regarding WAL streaming and backup from
standby
Version 2.4 - 25 May 2018
- Add standard and retry hook scripts for backup deletion (pre/post)
......@@ -578,7 +601,7 @@ Version 1.2.0 - 31 Jan 2013
* Added retention policy support to the logging infrastructure, the
"check" and the "status" commands
* The "check" command now integrates minimum redundancy control
* The "check" command now integrates minimum redundancy control
* Added retention policy states (valid, obsolete and potentially obsolete)
to "show-backup" and "list-backup" commands
......
Metadata-Version: 1.1
Name: barman
Version: 2.4
Version: 2.5
Summary: Backup and Recovery Manager for PostgreSQL
Home-page: http://www.pgbarman.org/
Author: 2ndQuadrant Limited
......
Metadata-Version: 1.1
Name: barman
Version: 2.4
Version: 2.5
Summary: Backup and Recovery Manager for PostgreSQL
Home-page: http://www.pgbarman.org/
Author: 2ndQuadrant Limited
......
......@@ -51,6 +51,7 @@ doc/barman.1.d/20-options.md
doc/barman.1.d/45-commands.md
doc/barman.1.d/50-archive-wal.md
doc/barman.1.d/50-backup.md
doc/barman.1.d/50-check-backup.md
doc/barman.1.d/50-check.md
doc/barman.1.d/50-cron.md
doc/barman.1.d/50-delete.md
......
......@@ -48,7 +48,7 @@ _logger = logging.getLogger(__name__)
class BackupManager(RemoteStatusMixin):
"""Manager of the backup archive for a server"""
DEFAULT_STATUS_FILTER = (BackupInfo.DONE,)
DEFAULT_STATUS_FILTER = BackupInfo.STATUS_COPY_DONE
def __init__(self, server):
"""
......@@ -246,7 +246,8 @@ class BackupManager(RemoteStatusMixin):
:param backup: the backup to delete
:return bool: True if deleted, False if could not delete the backup
"""
available_backups = self.get_available_backups()
available_backups = self.get_available_backups(
status_filter=(BackupInfo.DONE,))
minimum_redundancy = self.server.config.minimum_redundancy
# Honour minimum required redundancy
if backup.status == BackupInfo.DONE and \
......@@ -361,6 +362,8 @@ class BackupManager(RemoteStatusMixin):
def backup(self):
"""
Performs a backup for the server
:return BackupInfo: the generated BackupInfo
"""
_logger.debug("initialising backup information")
self.executor.init()
......@@ -395,8 +398,8 @@ class BackupManager(RemoteStatusMixin):
# Compute backup size and fsync it on disk
self.backup_fsync_and_set_sizes(backup_info)
# Mark the backup as DONE
backup_info.set_attribute("status", "DONE")
# Mark the backup as WAITING_FOR_WALS
backup_info.set_attribute("status", BackupInfo.WAITING_FOR_WALS)
# Use BaseException instead of Exception to catch events like
# KeyboardInterrupt (e.g.: CTRL-C)
except BaseException as e:
......@@ -458,6 +461,7 @@ class BackupManager(RemoteStatusMixin):
script.run()
output.result('backup', backup_info)
return backup_info
def recover(self, backup_info, dest, tablespaces=None, remote_command=None,
**kwargs):
......@@ -678,7 +682,8 @@ class BackupManager(RemoteStatusMixin):
)
check_strategy.init_check('minimum redundancy requirements')
# Minimum redundancy checks
no_backups = len(self.get_available_backups())
no_backups = len(self.get_available_backups(
status_filter=(BackupInfo.DONE,)))
# Check minimum_redundancy_requirements parameter
if no_backups < int(self.config.minimum_redundancy):
status = False
......@@ -700,7 +705,8 @@ class BackupManager(RemoteStatusMixin):
This function show the server status
"""
# get number of backups
no_backups = len(self.get_available_backups())
no_backups = len(self.get_available_backups(
status_filter=(BackupInfo.DONE,)))
output.result('status', self.config.name,
"backups_number",
"No. of available backups", no_backups)
......@@ -1003,3 +1009,84 @@ class BackupManager(RemoteStatusMixin):
else:
output.info("Backup size: %s" %
pretty_size(backup_info.size))
def check_backup(self, backup_info):
"""
Make sure that all the required WAL files to check
the consistency of a physical backup (that is, from the
beginning to the end of the full backup) are correctly
archived. This command is automatically invoked by the
cron command and at the end of every backup operation.
:param backup_info: the target backup
"""
# Gather the list of the latest archived wals
timelines = self.get_latest_archived_wals_info()
# Get the basic info for the backup
begin_wal = backup_info.begin_wal
end_wal = backup_info.end_wal
timeline = begin_wal[:8]
# Case 1: Barman still doesn't know about the timeline the backup
# started with. We still haven't archived any WAL corresponding
# to the backup, so we can't proceed with checking the existence
# of the required WAL files
if not timelines or timeline not in timelines:
backup_info.status = BackupInfo.WAITING_FOR_WALS
backup_info.save()
return
# Find the most recent archived WAL for this server in the timeline
# where the backup was taken
last_archived_wal = timelines[timeline].name
# Case 2: the most recent WAL file archived is older than the
# start of the backup. We must wait for the archiver to receive
# and/or process the WAL files.
if last_archived_wal < begin_wal:
backup_info.status = BackupInfo.WAITING_FOR_WALS
backup_info.save()
return
# Check the intersection between the required WALs and the archived
# ones. They should all exist
bound_end = min(last_archived_wal, end_wal)
segments = xlog.generate_segment_names(
begin_wal,
bound_end,
xlog_segment_size=backup_info.xlog_segment_size)
missing_wal = None
for wal in segments:
wal_full_path = self.server.get_wal_full_path(wal)
if not os.path.exists(wal_full_path):
missing_wal = wal
break
if missing_wal:
# Case 3: the most recent WAL file archived is more recent than
# the one corresponding to the start of a backup. If WAL
# file is missing, then we can't recover from the backup so we
# must mark the backup as FAILED.
# TODO: Verify if the error field is the right place
# to store the error message
backup_info.error = (
"At least one WAL file is missing. "
"The first missing WAL file is %s" % missing_wal)
backup_info.status = BackupInfo.FAILED
backup_info.save()
return
if end_wal <= last_archived_wal:
# Case 4: if the most recent WAL file archived is more recent or
# equal than the one corresponding to the end of the backup and
# every WAL that will be required by the recovery is available,
# we can mark the backup as DONE.
backup_info.status = BackupInfo.DONE
else:
# Case 5: if the most recent WAL file archived is older than
# the one corresponding to the end of the backup but
# all the WAL files until that point are present.
backup_info.status = BackupInfo.WAITING_FOR_WALS
backup_info.save()
......@@ -419,7 +419,7 @@ def recover(args):
# Retrieves the backup
backup_id = parse_backup_id(server, args)
if backup_id.status != BackupInfo.DONE:
if backup_id.status not in BackupInfo.STATUS_COPY_DONE:
output.error(
"Cannot recover from backup '%s' of server '%s': "
"backup status is not DONE",
......@@ -832,6 +832,32 @@ def receive_wal(args):
output.close_and_exit()
@named('check-backup')
@arg('server_name',
completer=server_completer,
help='specifies the server name for the command')
@arg('backup_id',
completer=backup_completer,
help='specifies the backup ID')
@expects_obj
def check_backup(args):
"""
Make sure that all the required WAL files to check
the consistency of a physical backup (that is, from the
beginning to the end of the full backup) are correctly
archived. This command is automatically invoked by the
cron command and at the end of every backup operation.
"""
server = get_server(args)
# Retrieves the backup
backup_info = parse_backup_id(server, args)
with closing(server):
server.check_backup(backup_info)
output.close_and_exit()
def pretty_args(args):
"""
Prettify the given argh namespace to be human readable
......@@ -1139,6 +1165,7 @@ def main():
archive_wal,
backup,
check,
check_backup,
cron,
delete,
diagnose,
......
......@@ -39,20 +39,6 @@ from barman.exceptions import CommandFailedException, CommandMaxRetryExceeded
_logger = logging.getLogger(__name__)
def _str(cmd_out):
"""
Make a string from the output of a CommandWrapper execution.
If input is None returns a literal 'None' string
:param cmd_out: String or ByteString to convert
:return str: a string
"""
if hasattr(cmd_out, 'decode') and callable(cmd_out.decode):
return cmd_out.decode('utf-8', 'replace')
else:
return str(cmd_out)
class StreamLineProcessor(object):
"""
Class deputed to reading lines from a file object, using a buffered read.
......@@ -93,7 +79,7 @@ class StreamLineProcessor(object):
# Handle the last line (always incomplete, maybe empty)
self._handler(self._buf)
return True
self._buf += data.decode('utf-8')
self._buf += data.decode('utf-8', 'replace')
# If no '\n' is present, we just read a part of a very long line.
# Nothing to do at the moment.
if '\n' not in self._buf:
......@@ -349,11 +335,6 @@ class Command(object):
self.out = '\n'.join(out)
self.err = '\n'.join(err)
# Ensure the output and the error or the command wrapper are
# really unicode strings
self.out = _str(self.out)
self.err = _str(self.err)
_logger.debug("Command stdout: %s", self.out)
_logger.debug("Command stderr: %s", self.err)
......
......@@ -27,6 +27,7 @@ import dateutil.tz
from barman import xlog
from barman.compression import identify_compression
from barman.exceptions import BackupInfoBadInitialisation
from barman.utils import fsync_dir
# Named tuple representing a Tablespace with 'name' 'oid' and 'location'
# as property.
......@@ -210,7 +211,7 @@ class FieldListFile(object):
else:
filename = filename or self.filename
if filename:
info = open(filename, 'w')
info = open(filename + '.tmp', 'w')
else:
info = None
......@@ -226,6 +227,10 @@ class FieldListFile(object):
value = field.to_str(value)
info.write("%s=%s\n" % (name, value))
if not file_object:
os.rename(filename + '.tmp', filename)
fsync_dir(os.path.normpath(os.path.dirname(filename)))
def load(self, filename=None, file_object=None):
"""
Replaces the current object content with the one deserialized from
......@@ -402,10 +407,12 @@ class BackupInfo(FieldListFile):
EMPTY = 'EMPTY'
STARTED = 'STARTED'
FAILED = 'FAILED'
WAITING_FOR_WALS = 'WAITING_FOR_WALS'
DONE = 'DONE'
STATUS_ALL = (EMPTY, STARTED, DONE, FAILED)
STATUS_NOT_EMPTY = (STARTED, DONE, FAILED)
STATUS_ARCHIVING = (STARTED, DONE)
STATUS_COPY_DONE = (WAITING_FOR_WALS, DONE)
STATUS_ALL = (EMPTY, STARTED, WAITING_FOR_WALS, DONE, FAILED)
STATUS_NOT_EMPTY = (STARTED, WAITING_FOR_WALS, DONE, FAILED)
STATUS_ARCHIVING = (STARTED, WAITING_FOR_WALS, DONE)
#: Status according to retention policies
OBSOLETE = 'OBSOLETE'
......
......@@ -287,3 +287,18 @@ class ServerWalReceiveLock(LockFile):
super(ServerWalReceiveLock, self).__init__(
os.path.join(lock_directory, '.%s-receive-wal.lock' % server_name),
raise_if_fail=True, wait=False)
class ServerBackupIdLock(LockFile):
"""
This lock protects from changing a backup that is in use.
Creates a '.<SERVER>-<BACKUP_ID>.lock' lock file under the given
lock_directory for a BACKUP of a SERVER.
"""
def __init__(self, lock_directory, server_name, backup_id):
super(ServerBackupIdLock, self).__init__(
os.path.join(lock_directory, '.%s-%s.lock' % (
server_name, backup_id)),
raise_if_fail=True, wait=False)
......@@ -552,7 +552,7 @@ class ConsoleOutputWriter(object):
out_list = [
"%s %s - " % (backup_info.server_name, backup_info.backup_id)]
if backup_info.status == BackupInfo.DONE:
if backup_info.status in BackupInfo.STATUS_COPY_DONE:
end_time = backup_info.end_time.ctime()
out_list.append('%s - Size: %s - WAL Size: %s' %
(end_time,
......@@ -584,7 +584,7 @@ class ConsoleOutputWriter(object):
self.info("Backup %s:", data['backup_id'])
self.info(" Server Name : %s", data['server_name'])
self.info(" Status : %s", data['status'])
if data['status'] == BackupInfo.DONE:
if data['status'] in BackupInfo.STATUS_COPY_DONE:
self.info(" PostgreSQL Version : %s", data['version'])
self.info(" PGDATA directory : %s", data['pgdata'])
if data['tablespaces']:
......
......@@ -576,22 +576,27 @@ class PostgreSQLConnection(PostgreSQL):
try:
cur = self._cursor(cursor_factory=DictCursor)
# We can't use the `get_setting` method here, because it
# use `SHOW`, returning an human readable value such as "16MB",
# while we prefer a raw value such as 16777216.
cur.execute("SELECT setting "
"FROM pg_settings "
"WHERE name='wal_block_size'")
result = cur.fetchone()
wal_block_size = int(result[0])
cur.execute("SELECT setting "
"FROM pg_settings "
"WHERE name='wal_segment_size'")
result = cur.fetchone()
wal_segment_size = int(result[0])
return wal_block_size * wal_segment_size
# Prior to PostgreSQL 11, the wal segment size is returned in
# blocks
if self.server_version < 110000:
cur.execute("SELECT setting "
"FROM pg_settings "
"WHERE name='wal_block_size'")
result = cur.fetchone()
wal_block_size = int(result[0])
wal_segment_size *= wal_block_size
return wal_segment_size
except ValueError as e:
_logger.error("Error retrieving current xlog "
"segment size: %s",
......
......@@ -124,6 +124,15 @@ class RecoveryExecutor(object):
backup_info.backup_id)
output.info("Destination directory: %s", dest)
# If the backup we are recovering is still not validated and we
# haven't requested the get-wal feature, display a warning message
if not recovery_info['get_wal']:
if backup_info.status == BackupInfo.WAITING_FOR_WALS:
output.warning(
"IMPORTANT: You have requested a recovery operation for "
"a backup that does not have yet all the WAL files that "
"are required for consistency.")
# Set targets for PITR
self._set_pitr_targets(recovery_info,
backup_info, dest,
......@@ -183,6 +192,19 @@ class RecoveryExecutor(object):
# Restore the WAL segments. If GET_WAL option is set, skip this phase
# as they will be retrieved using the wal-get command.
if not recovery_info['get_wal']:
# If the backup we restored is still waiting for WALS, read the
# backup info again and check whether it has been validated.
# Notify the user if it is still not DONE.
if backup_info.status == BackupInfo.WAITING_FOR_WALS:
data = BackupInfo(self.server, backup_info.filename)
if data.status == BackupInfo.WAITING_FOR_WALS:
output.warning(
"IMPORTANT: The backup we have recovered IS NOT "
"VALID. Required WAL files for consistency are "
"missing. Please verify that WAL archiving is "
"working correctly or evaluate using the 'get-wal' "
"option for recovery")
output.info("Copying required WAL segments.")
try:
......
This diff is collapsed.
......@@ -19,4 +19,4 @@
This module contains the current Barman version.
'''
__version__ = '2.4'
__version__ = '2.5'
......@@ -482,6 +482,9 @@ class FileWalArchiver(WalArchiver):
# Get the batch size from configuration (0 = unlimited)
batch_size = self.config.archiver_batch_size
# List and sort all files in the incoming directory
# IMPORTANT: the list is sorted, and this allows us to know that the
# WAL stream we have is monotonically increasing. That allows us to
# verify that a backup has all the WALs required for the restore.
file_names = glob(os.path.join(
self.config.incoming_wals_directory, '*'))
file_names.sort()
......@@ -793,7 +796,10 @@ class StreamingWalArchiver(WalArchiver):
"""
# Get the batch size from configuration (0 = unlimited)
batch_size = self.config.streaming_archiver_batch_size
# List and sort all files in the incoming directory
# List and sort all files in the incoming directory.
# IMPORTANT: the list is sorted, and this allows us to know that the
# WAL stream we have is monotonically increasing. That allows us to
# verify that a backup has all the WALs required for the restore.
file_names = glob(os.path.join(
self.config.streaming_wals_directory, '*'))
file_names.sort()
......
.\" Automatically generated by Pandoc 2.2
.\" Automatically generated by Pandoc 2.3.1
.\"
.TH "BARMAN" "1" "May 25, 2018" "Barman User manuals" "Version 2.4"
.TH "BARMAN" "1" "October 23, 2018" "Barman User manuals" "Version 2.5"
.hy
.SH NAME
.PP
......@@ -115,6 +115,15 @@ the configuration file.
.RE
.RE
.TP
.B check\-backup \f[I]SERVER_NAME\f[] \f[I]BACKUP_ID\f[]
Make sure that all the required WAL files to check the consistency of a
physical backup (that is, from the beginning to the end of the full
backup) are correctly archived.
This command is automatically invoked by the \f[C]cron\f[] command and
at the end of every backup operation.
.RS
.RE
.TP
.B check \f[I]SERVER_NAME\f[]
Show diagnostic information about \f[C]SERVER_NAME\f[], including: Ssh
connection check, PostgreSQL version, configuration and backup
......@@ -507,12 +516,14 @@ Use this option with care.
Wait for one xlog file to be archived.
If after a defined amount of time (default: 30 seconds) no xlog file is
archived, Barman will teminate with failure exit code.
Available also on standby servers.
.RS
.RE
.TP
.B \-\-archive\-timeout \f[I]TIMEOUT\f[]
Specifies the amount of time in seconds (default: 30 seconds) the
archiver will wait for a new xlog file to be archived before timing out.
Available also on standby servers.
.RS
.RE
.RE
......
% BARMAN(1) Barman User manuals | Version 2.4
% BARMAN(1) Barman User manuals | Version 2.5
% 2ndQuadrant Limited <https://www.2ndQuadrant.com>
% May 25, 2018
% October 23, 2018
check-backup *SERVER_NAME* *BACKUP_ID*
: Make sure that all the required WAL files to check
the consistency of a physical backup (that is, from the
beginning to the end of the full backup) are correctly
archived. This command is automatically invoked by the
`cron` command and at the end of every backup operation.
......@@ -11,8 +11,10 @@ switch-wal *SERVER_NAME*
: Wait for one xlog file to be archived.
If after a defined amount of time (default: 30 seconds) no xlog
file is archived, Barman will teminate with failure exit code.
Available also on standby servers.
--archive-timeout *TIMEOUT*
: Specifies the amount of time in seconds (default: 30 seconds)
the archiver will wait for a new xlog file to be archived
before timing out.
Available also on standby servers.
.\" Automatically generated by Pandoc 2.2
.\" Automatically generated by Pandoc 2.3.1
.\"
.TH "BARMAN" "5" "May 25, 2018" "Barman User manuals" "Version 2.4"
.TH "BARMAN" "5" "October 23, 2018" "Barman User manuals" "Version 2.5"
.hy
.SH NAME
.PP
......
% BARMAN(5) Barman User manuals | Version 2.4
% BARMAN(5) Barman User manuals | Version 2.5
% 2ndQuadrant Limited <https://www.2ndQuadrant.com>
% May 25, 2018
% October 23, 2018
% Barman Manual
% 2ndQuadrant Limited
% May 25, 2018 (v2.4)
% October 23, 2018 (v2.5)
**Barman** (Backup and Recovery Manager) is an open-source administration tool for disaster recovery of PostgreSQL servers written in Python. It allows your organisation to perform remote backups of multiple servers in business critical environments to reduce risk and help DBAs during the recovery phase.
......
......@@ -26,6 +26,32 @@ barman delete <server_name> oldest
to remove the oldest backup available in the catalog and reclaim disk space.
## `check-backup`
Starting with version 2.5, you can check that all required WAL files
for the consistency of a full backup have been correctly archived by
`barman` with the `check-backup` command:
``` bash
barman check-backup <server_name> <backup_id>
```
> **IMPORTANT:**
> This command is automatically invoked by `cron` and at the end of a
> `backup` operation. This means that, under normal circumstances,
> you should never need to execute it.
In case one or more WAL files from the start to the end of the backup
have not been archived yet, `barman` will label the backup as
`WAITING_FOR_WALS`. The `cron` command will continue to check that
missing WAL files are archived, then label the backup as `DONE`.
In case the first required WAL file is missing at the end of the
backup, such backup will be marked as `FAILED`. It is therefore
important that you verify that WAL archiving (whether via streaming
or `archive_command`) is properly working before executing a backup
operation - especially when backing up from a standby server.
## `delete`
You can delete a given backup with:
......
......@@ -162,14 +162,15 @@ rules:
greater, concurrent backups are executed through the Postgres native
API.
The destination Postgres server can be either the master or a
The destination Postgres server can be either the master (preferred) or a
streaming replicated standby server.
> **NOTE:**
> When backing up from a standby server, continuous archiving of WAL
> files must be configured on the master to ship files to the Barman
> server (as outlined in the _"WAL archiving via archive_command"_ section
> above)[^CONCURRENT_ARCHIVING].
> **IMPORTANT:**
> When backing up from a standby server, the **only way to ship WAL files to
> Barman** that is currently supported is from the master server.
> This can happen either via traditional WAL archiving with `archive_command`
> (as outlined in the _"WAL archiving via archive_command"_ section
> above)[^CONCURRENT_ARCHIVING], or via WAL streaming (with replication slots).
[^CONCURRENT_ARCHIVING]:
In case of a concurrent backup, currently Barman has no way
......@@ -178,7 +179,9 @@ streaming replicated standby server.
where PostgreSQL itself makes sure that the WAL file is correctly
archived. Be aware that the full backup cannot be considered
consistent until that WAL file has been received and archived by
Barman.
Barman. Barman 2.5 introduces a new state, called `WAITING_FOR_WALS`,
which is managed by the `check-backup` command (part of the
ordinary maintenance job performed by the `cron` command).
## Archiving features
......
......@@ -8,6 +8,7 @@ Below you will find a matrix of PostgreSQL versions and Barman features for back
| **Version** | **Backup with rsync/SSH** | **Backup with pg_basebackup** | **Standard WAL archiving** | **WAL Streaming** | **RPO=0** |
|:---------:|:---------------------:|:-------------------------:|:----------------------:|:----------------------:|:-------:|
| **11** | Yes | Yes | Yes | Yes | Yes |
| **10** | Yes | Yes | Yes | Yes | Yes |
| **9.6** | Yes | Yes | Yes | Yes | Yes |
| **9.5** | Yes | Yes | Yes | Yes | Yes ~(d)~ |
......@@ -31,7 +32,7 @@ d) When using `pg_receivexlog` 9.5, minor version 9.5.5 or higher required [^com
It is required by Barman that `pg_basebackup` and `pg_receivewal`/`pg_receivexlog` of the same version of the PostgreSQL server (or higher) are installed on the same server where Barman resides. The only exception is that PostgreSQL 9.2 users are required to install version 9.2 of `pg_basebackup` and `pg_receivexlog` alongside with Barman.
>> **TIP:** We recommend that the last major, stable version of the PostgreSQL clients (e.g. 10) is installed on the Barman server if you plan to use backup and WAL archiving over streaming replication through `pg_basebackup` and `pg_receivewal`, for PostgreSQL 9.3 or higher servers.
>> **TIP:** We recommend that the last major, stable version of the PostgreSQL clients (e.g. 11) is installed on the Barman server if you plan to use backup and WAL archiving over streaming replication through `pg_basebackup` and `pg_receivewal`, for PostgreSQL 9.3 or higher servers.