diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index b37f1d19b27..fcf22b7cd14 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -941,7 +941,29 @@ logical_read_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int req am_cascading_walsender = RecoveryInProgress(); if (am_cascading_walsender) - GetXLogReplayRecPtr(&currTLI); + { + TimeLineID insertTLI; + + /* + * If the insertion timeline has already been set, use it. + * InsertTimeLineID is set before the WAL segments of the old timeline + * are removed, before SharedRecoveryState switches to + * RECOVERY_STATE_DONE. + * + * There is a window where RecoveryInProgress() still returns true but + * the old timeline's WAL segments have already been removed or + * recycled. Using the WAL insertion timeline avoids attempting to + * read from those removed segments, improving availability, and is a + * safe thing to do as promotion copies the contents in the last + * segment of the old timeline to the first segment of the new + * timeline, up to the switchpoint. + */ + insertTLI = GetWALInsertionTimeLineIfSet(); + if (insertTLI != 0) + currTLI = insertTLI; + else + GetXLogReplayRecPtr(&currTLI); + } else currTLI = GetWALInsertionTimeLine();