Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix possibility of creating a "phantom" segment after promotion.
authorAndres Freund <andres@anarazel.de>
Wed, 21 Jun 2017 21:14:21 +0000 (14:14 -0700)
committerAndres Freund <andres@anarazel.de>
Wed, 21 Jun 2017 21:14:21 +0000 (14:14 -0700)
When promoting a standby just after a XLOG_SWITCH record was replayed,
and next segment(s) are already are locally available (via walsender,
restore_command + trigger/recovery target), that segment could
accidentally be recycled onto the past of the new timeline.  Later
checkpointer would create a .ready file for it, assuming there was an
error during creation, and it would get archived.  That causes trouble
if another standby is later brought up from a basebackup from before
the timeline creation, because it would try to read the
segment, because XLogFileReadAnyTLI just tries all possible timelines,
which doesn't have valid contents.  Thus replay would fail.

The problem, if already occurred, can be fixed by removing the segment
and/or having restore_command filter it out.

The reason for the creation of such "phantom" segments was, that after
an XLOG_SWITCH record the EndOfLog variable points to the beginning of
the next segment, and RemoveXlogFile() used XLByteToPrevSeg().
Normally RemoveXlogFile() doing so is harmless, because the last
segment will still exist preventing InstallXLogFileSegment() from
causing harm, but just after promotion there's no previous segment on
the new timeline.

Fix that by using XLByteToSeg() instead of XLByteToPrevSeg().

Author: Andres Freund
Reported-By: Greg Burek
Discussion: https://postgr.es/m/20170619073026.zcwpe6mydsaz5ygd@alap3.anarazel.de
Backpatch: 9.2-, bug older than all supported versions

src/backend/access/transam/xlog.c

index 2115a14a6051b10ba3220a0306e1d8b109348286..3b2fefe932efd0b08096b1734045df7c50e38854 100644 (file)
@@ -3860,7 +3860,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr endptr)
     * Initialize info about where to try to recycle to.  We allow recycling
     * segments up to XLOGfileslop segments beyond the current XLOG location.
     */
-   XLByteToPrevSeg(endptr, endlogSegNo);
+   XLByteToSeg(endptr, endlogSegNo);
    max_advance = XLOGfileslop;
 
    snprintf(path, MAXPGPATH, XLOGDIR "/%s", segname);