diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index b3468eea3cb..91da3c26ba0 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -892,7 +892,11 @@ test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/0
only the incremental backup itself but also all earlier backups that
are required to supply the blocks omitted from the incremental backup.
See for further information about
- this requirement.
+ this requirement. Note that there are restrictions on the use of
+ pg_combinebackup when the checksum status of the
+ cluster has been changed; see
+ pg_combinebackup
+ limitations.
diff --git a/doc/src/sgml/ref/pg_combinebackup.sgml b/doc/src/sgml/ref/pg_combinebackup.sgml
index 96df3d81f15..d1f70ba2358 100644
--- a/doc/src/sgml/ref/pg_combinebackup.sgml
+++ b/doc/src/sgml/ref/pg_combinebackup.sgml
@@ -261,6 +261,26 @@ PostgreSQL documentation
+
+ Limitations
+
+
+ pg_combinebackup does not recompute page checksums when
+ writing the output directory. Therefore, if any of the backups used for
+ reconstruction were taken with checksums disabled, but the final backup was
+ taken with checksums enabled, the resulting directory may contain pages
+ with invalid checksums.
+
+
+
+ To avoid this problem, taking a new full backup after changing the checksum
+ state of the cluster using is
+ recommended. Otherwise, you can disable and then optionally reenable
+ checksums on the directory produced by pg_combinebackup
+ in order to correct the problem.
+
+
+
Environment
diff --git a/src/bin/pg_combinebackup/pg_combinebackup.c b/src/bin/pg_combinebackup/pg_combinebackup.c
index 4958372653b..232ba5b0697 100644
--- a/src/bin/pg_combinebackup/pg_combinebackup.c
+++ b/src/bin/pg_combinebackup/pg_combinebackup.c
@@ -583,6 +583,8 @@ check_control_files(int n_backups, char **backup_dirs)
{
int i;
uint64 system_identifier = 0; /* placate compiler */
+ uint32 data_checksum_version = 0; /* placate compiler */
+ bool data_checksum_mismatch = false;
/* Try to read each control file in turn, last to first. */
for (i = n_backups - 1; i >= 0; --i)
@@ -612,6 +614,16 @@ check_control_files(int n_backups, char **backup_dirs)
controlpath, (unsigned long long) system_identifier,
(unsigned long long) control_file->system_identifier);
+ /*
+ * Detect checksum mismatches, but only if the last backup in the
+ * chain has checksums enabled.
+ */
+ if (i == n_backups - 1)
+ data_checksum_version = control_file->data_checksum_version;
+ else if (data_checksum_version != 0 &&
+ data_checksum_version != control_file->data_checksum_version)
+ data_checksum_mismatch = true;
+
/* Release memory. */
pfree(control_file);
pfree(controlpath);
@@ -624,6 +636,16 @@ check_control_files(int n_backups, char **backup_dirs)
pg_log_debug("system identifier is %llu",
(unsigned long long) system_identifier);
+ /*
+ * Warn the user if not all backups are in the same state with regards to
+ * checksums.
+ */
+ if (data_checksum_mismatch)
+ {
+ pg_log_warning("only some backups have checksums enabled");
+ pg_log_warning_hint("disable, and optionally reenable, checksums on the output directory to avoid failures");
+ }
+
return system_identifier;
}