From 775f6366d78ac6818023cc158e37c70119246e19 Mon Sep 17 00:00:00 2001 From: Kyotaro Horiguchi Date: Fri, 26 Oct 2018 10:07:05 +0900 Subject: [PATCH 5/5] Check removal of in-read segment file. Checkpoint can remove or recycle a segment file while it is being read by ReadRecord. This patch checks for the case and error out immedaitely. Reading recycled file is basically safe and inconsistenty caused by overwrites as new segment will be caught by page/record validation. So this is only for keeping consistency with the wal_status shown in pg_replication_slots. --- src/backend/access/transam/xlogreader.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index 0768ca7822..a6c97cf260 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -217,6 +217,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg) { XLogRecord *record; XLogRecPtr targetPagePtr; + XLogSegNo targetSegNo; bool randAccess; uint32 len, total_len; @@ -270,6 +271,18 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg) targetPagePtr = RecPtr - (RecPtr % XLOG_BLCKSZ); targetRecOff = RecPtr % XLOG_BLCKSZ; + /* + * checkpoint can remove the segment currently looking for. make sure the + * current segment is still exists. We check this only once per record. + */ + XLByteToSeg(targetPagePtr, targetSegNo, state->wal_segment_size); + if (targetSegNo <= XLogGetLastRemovedSegno()) + ereport(ERROR, + (errcode(ERRCODE_NO_DATA), + errmsg("WAL record at %X/%X no longer available", + (uint32)(RecPtr >> 32), (uint32) RecPtr), + errdetail("The segment for the record has been removed."))); + /* * Read the page containing the record into state->readBuf. Request enough * byte to cover the whole record header, or at least the part of it that -- 2.16.3