diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index ef72bde012..757760eada 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -4419,12 +4419,18 @@ ReadRecord(XLogReaderState *xlogreader, int emode, if (record == NULL) { /* - * When not in standby mode we find that WAL ends in an incomplete - * record, keep track of that record. After recovery is done, - * we'll write a record to indicate downstream WAL readers that - * that portion is to be ignored. + * When we find that WAL ends in an incomplete record, keep track + * of that record. After recovery is done, we'll write a record to + * indicate to downstream WAL readers that that portion is to be + * ignored. + * + * However, when ArchiveRecoveryRequested = true, we're going to + * switch to a new timeline at the end of recovery. We will only + * copy WAL over to the new timeline up to the end of the last + * complete record, so if we did this, we would later create an + * overwrite contrecord in the wrong place, breaking everything. */ - if (!StandbyMode && + if (!ArchiveRecoveryRequested && !XLogRecPtrIsInvalid(xlogreader->abortedRecPtr)) { abortedRecPtr = xlogreader->abortedRecPtr; @@ -7866,6 +7872,14 @@ StartupXLOG(void) */ if (!XLogRecPtrIsInvalid(missingContrecPtr)) { + /* + * We should only have a missingContrecPtr if we're not switching to + * a new timeline. When a timeline switch occurs, WAL is copied from + * the old timeline to the new only up to the end of the last complete + * record, so there can't be an incomplete WAL record that we need to + * disregard. + */ + Assert(ThisTimeLineID == PrevTimeLineID); Assert(!XLogRecPtrIsInvalid(abortedRecPtr)); EndOfLog = missingContrecPtr; }