diff -Nacr a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c *** a/src/backend/access/transam/xlog.c 2016-08-09 05:33:27.000000000 +0900 --- b/src/backend/access/transam/xlog.c 2016-08-26 10:27:55.000000000 +0900 *************** *** 589,596 **** /* State information for XLOG reading */ static XLogRecPtr ReadRecPtr; /* start of last record read */ static XLogRecPtr EndRecPtr; /* end+1 of last record read */ ! static TimeLineID lastPageTLI = 0; ! static TimeLineID lastSegmentTLI = 0; static XLogRecPtr minRecoveryPoint; /* local copy of * ControlFile->minRecoveryPoint */ --- 589,596 ---- /* State information for XLOG reading */ static XLogRecPtr ReadRecPtr; /* start of last record read */ static XLogRecPtr EndRecPtr; /* end+1 of last record read */ ! static XLogRecPtr latestPagePtr; /* start of last page read */ ! static TimeLineID latestPageTLI = 0; static XLogRecPtr minRecoveryPoint; /* local copy of * ControlFile->minRecoveryPoint */ *************** *** 678,684 **** static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force); static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt); static void CheckRecoveryConsistency(void); ! static bool ValidXLOGHeader(XLogPageHeader hdr, int emode, bool segmentonly); static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt); static List *readTimeLineHistory(TimeLineID targetTLI); static bool existsTimeLineHistory(TimeLineID probeTLI); --- 678,684 ---- static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force); static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt); static void CheckRecoveryConsistency(void); ! static bool ValidXLOGHeader(XLogPageHeader hdr, int emode); static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr, int whichChkpt); static List *readTimeLineHistory(TimeLineID targetTLI); static bool existsTimeLineHistory(TimeLineID probeTLI); *************** *** 3992,4005 **** (errmsg("invalid record offset at %X/%X", RecPtr->xlogid, RecPtr->xrecoff))); - /* - * Since we are going to a random position in WAL, forget any prior - * state about what timeline we were in, and allow it to be any - * timeline in expectedTLIs. We also set a flag to allow curFileTLI - * to go backwards (but we can't reset that variable right here, since - * we might not change files at all). - */ - lastPageTLI = lastSegmentTLI = 0; /* see comment in ValidXLOGHeader */ randAccess = true; /* allow curFileTLI to go backwards too */ } --- 3992,3997 ---- *************** *** 4317,4323 **** * ReadRecord. It's not intended for use from anywhere else. */ static bool ! ValidXLOGHeader(XLogPageHeader hdr, int emode, bool segmentonly) { XLogRecPtr recaddr; --- 4309,4315 ---- * ReadRecord. It's not intended for use from anywhere else. */ static bool ! ValidXLOGHeader(XLogPageHeader hdr, int emode) { XLogRecPtr recaddr; *************** *** 4411,4441 **** * immediate parent's TLI, we should never see TLI go backwards across * successive pages of a consistent WAL sequence. * ! * Of course this check should only be applied when advancing sequentially ! * across pages; therefore ReadRecord resets lastPageTLI and ! * lastSegmentTLI to zero when going to a random page. ! * ! * Sometimes we re-open a segment that's already been partially replayed. ! * In that case we cannot perform the normal TLI check: if there is a ! * timeline switch within the segment, the first page has a smaller TLI ! * than later pages following the timeline switch, and we might've read ! * them already. As a weaker test, we still check that it's not smaller ! * than the TLI we last saw at the beginning of a segment. Pass ! * segmentonly = true when re-validating the first page like that, and the ! * page you're actually interested in comes later. */ ! if (hdr->xlp_tli < (segmentonly ? lastSegmentTLI : lastPageTLI)) { ! ereport(emode_for_corrupt_record(emode, recaddr), ! (errmsg("out-of-sequence timeline ID %u (after %u) in log file %u, segment %u, offset %u", ! hdr->xlp_tli, ! segmentonly ? lastSegmentTLI : lastPageTLI, ! readId, readSeg, readOff))); ! return false; } ! lastPageTLI = hdr->xlp_tli; ! if (readOff == 0) ! lastSegmentTLI = hdr->xlp_tli; return true; } --- 4403,4426 ---- * immediate parent's TLI, we should never see TLI go backwards across * successive pages of a consistent WAL sequence. * ! * Sometimes we re-read a segment that's already been (partially) read. So ! * we only verify TLIs for pages that are later than the last remembered ! * LSN. */ ! if (XLByteLT(latestPagePtr, recaddr)) { ! if (hdr->xlp_tli < latestPageTLI) ! { ! ereport(emode_for_corrupt_record(emode, recaddr), ! (errmsg("out-of-sequence timeline ID %u (after %u) in log file %u, segment %u, offset %u", ! hdr->xlp_tli, ! latestPageTLI, ! readId, readSeg, readOff))); ! return false; ! } } ! latestPagePtr = recaddr; ! latestPageTLI = hdr->xlp_tli; return true; } *************** *** 10803,10809 **** readId, readSeg, readOff))); goto next_record_is_invalid; } ! if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, true)) goto next_record_is_invalid; } --- 10788,10794 ---- readId, readSeg, readOff))); goto next_record_is_invalid; } ! if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode)) goto next_record_is_invalid; } *************** *** 10825,10831 **** readId, readSeg, readOff))); goto next_record_is_invalid; } ! if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, false)) goto next_record_is_invalid; Assert(targetId == readId); --- 10810,10816 ---- readId, readSeg, readOff))); goto next_record_is_invalid; } ! if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode)) goto next_record_is_invalid; Assert(targetId == readId);