mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +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 commits2c03216d83and2076db2aea. 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:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user