]> granicus.if.org Git - postgresql/commitdiff
Fix WAL recycling on standbys depending on archive_mode
authorMichael Paquier <michael@paquier.xyz>
Fri, 28 Sep 2018 02:55:43 +0000 (11:55 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 28 Sep 2018 02:55:43 +0000 (11:55 +0900)
A restart point or a checkpoint recycling WAL segments treats segments
marked with neither ".done" (archiving is done) or ".ready" (segment is
ready to be archived) in archive_status the same way for archive_mode
being "on" or "always".  While for a primary this is fine, a standby
running a restart point with archive_mode = on would try to mark such a
segment as ready for archiving, which is something that will never
happen except after the standby is promoted.

Note that this problem applies only to WAL segments coming from the
local pg_wal the first time archive recovery is run.  Segments part of a
self-contained base backup are the most common case where this could
happen, however even in this case normally the .done markers would be
most likely part of the backup.  Segments recovered from an archive are
marked as .ready or .done by the startup process, and segments finished
streaming are marked as such by the WAL receiver, so they are handled
already.

Reported-by: Haruka Takatsuka
Author: Michael Paquier
Discussion: https://postgr.es/m/15402-a453c90ed4cf88b2@postgresql.org
Backpatch-through: 9.5, where archive_mode = always has been added.

src/backend/access/transam/xlogarchive.c

index 5c6de4989c9a41f82ff77d4a561cacda21903915..b3f0602ffd49560c3f5530ab94649dfce6161053 100644 (file)
@@ -620,9 +620,16 @@ XLogArchiveCheckDone(const char *xlog)
 {
        char            archiveStatusPath[MAXPGPATH];
        struct stat stat_buf;
+       bool            inRecovery = RecoveryInProgress();
 
-       /* Always deletable if archiving is off */
-       if (!XLogArchivingActive())
+       /*
+        * The file is always deletable if archive_mode is "off".  On standbys
+        * archiving is disabled if archive_mode is "on", and enabled with
+        * "always".  On a primary, archiving is enabled if archive_mode is "on"
+        * or "always".
+        */
+       if (!((XLogArchivingActive() && !inRecovery) ||
+                 (XLogArchivingAlways() && inRecovery)))
                return true;
 
        /* First check for .done --- this means archiver is done with it */