mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Attach FPI to the first record after full_page_writes is turned on.
XLogInsert fails to attach a required FPI to the first record after full_page_writes is turned on by the last checkpoint. This bug got introduced in 9.5 due to code rearrangement in commits 2c03216d83 and 2076db2aea. Fix it by ensuring that XLogInsertRecord performs a recomputation when the given record is generated with FPW as off but found that the flag has been turned on while actually inserting the record. Reported-by: Kyotaro Horiguchi Author: Kyotaro Horiguchi Reviewed-by: Amit Kapila Backpatch-through: 9.5 where this problem was introduced Discussion: https://postgr.es/m/20180420.151043.74298611.horiguchi.kyotaro@lab.ntt.co.jp
This commit is contained in:
parent
12368f5e83
commit
ff4220ead2
@ -943,7 +943,7 @@ static void WALInsertLockUpdateInsertingAt(XLogRecPtr insertingAt);
|
|||||||
*
|
*
|
||||||
* If 'fpw_lsn' is valid, it is the oldest LSN among the pages that this
|
* If 'fpw_lsn' is valid, it is the oldest LSN among the pages that this
|
||||||
* WAL record applies to, that were not included in the record as full page
|
* WAL record applies to, that were not included in the record as full page
|
||||||
* images. If fpw_lsn >= RedoRecPtr, the function does not perform the
|
* images. If fpw_lsn <= RedoRecPtr, the function does not perform the
|
||||||
* insertion and returns InvalidXLogRecPtr. The caller can then recalculate
|
* insertion and returns InvalidXLogRecPtr. The caller can then recalculate
|
||||||
* which pages need a full-page image, and retry. If fpw_lsn is invalid, the
|
* which pages need a full-page image, and retry. If fpw_lsn is invalid, the
|
||||||
* record is always inserted.
|
* record is always inserted.
|
||||||
@ -976,6 +976,7 @@ XLogInsertRecord(XLogRecData *rdata,
|
|||||||
info == XLOG_SWITCH);
|
info == XLOG_SWITCH);
|
||||||
XLogRecPtr StartPos;
|
XLogRecPtr StartPos;
|
||||||
XLogRecPtr EndPos;
|
XLogRecPtr EndPos;
|
||||||
|
bool prevDoPageWrites = doPageWrites;
|
||||||
|
|
||||||
/* we assume that all of the record header is in the first chunk */
|
/* we assume that all of the record header is in the first chunk */
|
||||||
Assert(rdata->len >= SizeOfXLogRecord);
|
Assert(rdata->len >= SizeOfXLogRecord);
|
||||||
@ -1023,10 +1024,14 @@ XLogInsertRecord(XLogRecData *rdata,
|
|||||||
WALInsertLockAcquire();
|
WALInsertLockAcquire();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if my copy of RedoRecPtr or doPageWrites is out of date.
|
* Check to see if my copy of RedoRecPtr is out of date. If so, may have
|
||||||
* If so, may have to go back and have the caller recompute everything.
|
* to go back and have the caller recompute everything. This can only
|
||||||
* This can only happen just after a checkpoint, so it's better to be slow
|
* happen just after a checkpoint, so it's better to be slow in this case
|
||||||
* in this case and fast otherwise.
|
* and fast otherwise.
|
||||||
|
*
|
||||||
|
* Also check to see if fullPageWrites or forcePageWrites was just turned
|
||||||
|
* on; if we weren't already doing full-page writes then go back and
|
||||||
|
* recompute.
|
||||||
*
|
*
|
||||||
* If we aren't doing full-page writes then RedoRecPtr doesn't actually
|
* If we aren't doing full-page writes then RedoRecPtr doesn't actually
|
||||||
* affect the contents of the XLOG record, so we'll update our local copy
|
* affect the contents of the XLOG record, so we'll update our local copy
|
||||||
@ -1041,7 +1046,9 @@ XLogInsertRecord(XLogRecData *rdata,
|
|||||||
}
|
}
|
||||||
doPageWrites = (Insert->fullPageWrites || Insert->forcePageWrites);
|
doPageWrites = (Insert->fullPageWrites || Insert->forcePageWrites);
|
||||||
|
|
||||||
if (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr && doPageWrites)
|
if (doPageWrites &&
|
||||||
|
(!prevDoPageWrites ||
|
||||||
|
(fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr)))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Oops, some buffer now needs to be backed up that the caller didn't
|
* Oops, some buffer now needs to be backed up that the caller didn't
|
||||||
|
Loading…
x
Reference in New Issue
Block a user