Skip to content

Commit 9915735

Browse files
committed
Fix calculation for WAL segment recycling and removal
Commit 4b0d28d has removed the prior checkpoint and related facilities but has left WAL recycling based on the LSN of the prior checkpoint, which causes incorrect calculations for WAL removal and recycling for max_wal_size and min_wal_size. This commit changes things so as the base calculation point is the last checkpoint generated. Reported-by: Kyotaro Horiguchi Author: Kyotaro Horiguchi Reviewed-by: Michael Paquier Discussion: https://postgr.es/m/20180723.135748.42558387.horiguchi.kyotaro@lab.ntt.co.jp Backpatch: 11-, where the prior checkpoint has been removed.
1 parent 14ca287 commit 9915735

File tree

1 file changed

+78
-81
lines changed
  • src/backend/access/transam

1 file changed

+78
-81
lines changed

src/backend/access/transam/xlog.c

Lines changed: 78 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -887,8 +887,8 @@ static bool WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
887887
static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr);
888888
static void XLogFileClose(void);
889889
static void PreallocXlogFiles(XLogRecPtr endptr);
890-
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr);
891-
static void RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr);
890+
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr RedoRecPtr, XLogRecPtr endptr);
891+
static void RemoveXlogFile(const char *segname, XLogRecPtr RedoRecPtr, XLogRecPtr endptr);
892892
static void UpdateLastRemovedPtr(char *filename);
893893
static void ValidateXLOGDirectoryStructure(void);
894894
static void CleanupBackupHistory(void);
@@ -2286,7 +2286,7 @@ assign_checkpoint_completion_target(double newval, void *extra)
22862286
* XLOG segments? Returns the highest segment that should be preallocated.
22872287
*/
22882288
static XLogSegNo
2289-
XLOGfileslop(XLogRecPtr PriorRedoPtr)
2289+
XLOGfileslop(XLogRecPtr RedoRecPtr)
22902290
{
22912291
XLogSegNo minSegNo;
22922292
XLogSegNo maxSegNo;
@@ -2298,9 +2298,9 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
22982298
* correspond to. Always recycle enough segments to meet the minimum, and
22992299
* remove enough segments to stay below the maximum.
23002300
*/
2301-
minSegNo = PriorRedoPtr / wal_segment_size +
2301+
minSegNo = RedoRecPtr / wal_segment_size +
23022302
ConvertToXSegs(min_wal_size_mb, wal_segment_size) - 1;
2303-
maxSegNo = PriorRedoPtr / wal_segment_size +
2303+
maxSegNo = RedoRecPtr / wal_segment_size +
23042304
ConvertToXSegs(max_wal_size_mb, wal_segment_size) - 1;
23052305

23062306
/*
@@ -2315,7 +2315,7 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
23152315
/* add 10% for good measure. */
23162316
distance *= 1.10;
23172317

2318-
recycleSegNo = (XLogSegNo) ceil(((double) PriorRedoPtr + distance) /
2318+
recycleSegNo = (XLogSegNo) ceil(((double) RedoRecPtr + distance) /
23192319
wal_segment_size);
23202320

23212321
if (recycleSegNo < minSegNo)
@@ -3866,12 +3866,12 @@ UpdateLastRemovedPtr(char *filename)
38663866
/*
38673867
* Recycle or remove all log files older or equal to passed segno.
38683868
*
3869-
* endptr is current (or recent) end of xlog, and PriorRedoRecPtr is the
3870-
* redo pointer of the previous checkpoint. These are used to determine
3869+
* endptr is current (or recent) end of xlog, and RedoRecPtr is the
3870+
* redo pointer of the last checkpoint. These are used to determine
38713871
* whether we want to recycle rather than delete no-longer-wanted log files.
38723872
*/
38733873
static void
3874-
RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
3874+
RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr RedoRecPtr, XLogRecPtr endptr)
38753875
{
38763876
DIR *xldir;
38773877
struct dirent *xlde;
@@ -3914,7 +3914,7 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
39143914
/* Update the last removed location in shared memory first */
39153915
UpdateLastRemovedPtr(xlde->d_name);
39163916

3917-
RemoveXlogFile(xlde->d_name, PriorRedoPtr, endptr);
3917+
RemoveXlogFile(xlde->d_name, RedoRecPtr, endptr);
39183918
}
39193919
}
39203920
}
@@ -3988,14 +3988,14 @@ RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
39883988
/*
39893989
* Recycle or remove a log file that's no longer needed.
39903990
*
3991-
* endptr is current (or recent) end of xlog, and PriorRedoRecPtr is the
3992-
* redo pointer of the previous checkpoint. These are used to determine
3991+
* endptr is current (or recent) end of xlog, and RedoRecPtr is the
3992+
* redo pointer of the last checkpoint. These are used to determine
39933993
* whether we want to recycle rather than delete no-longer-wanted log files.
3994-
* If PriorRedoRecPtr is not known, pass invalid, and the function will
3995-
* recycle, somewhat arbitrarily, 10 future segments.
3994+
* If RedoRecPtr is not known, pass invalid, and the function will recycle,
3995+
* somewhat arbitrarily, 10 future segments.
39963996
*/
39973997
static void
3998-
RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
3998+
RemoveXlogFile(const char *segname, XLogRecPtr RedoRecPtr, XLogRecPtr endptr)
39993999
{
40004000
char path[MAXPGPATH];
40014001
#ifdef WIN32
@@ -4009,10 +4009,10 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr)
40094009
* Initialize info about where to try to recycle to.
40104010
*/
40114011
XLByteToSeg(endptr, endlogSegNo, wal_segment_size);
4012-
if (PriorRedoPtr == InvalidXLogRecPtr)
4012+
if (RedoRecPtr == InvalidXLogRecPtr)
40134013
recycleSegNo = endlogSegNo + 10;
40144014
else
4015-
recycleSegNo = XLOGfileslop(PriorRedoPtr);
4015+
recycleSegNo = XLOGfileslop(RedoRecPtr);
40164016

40174017
snprintf(path, MAXPGPATH, XLOGDIR "/%s", segname);
40184018

@@ -8639,6 +8639,7 @@ CreateCheckPoint(int flags)
86398639
bool shutdown;
86408640
CheckPoint checkPoint;
86418641
XLogRecPtr recptr;
8642+
XLogSegNo _logSegNo;
86428643
XLogCtlInsert *Insert = &XLogCtl->Insert;
86438644
uint32 freespace;
86448645
XLogRecPtr PriorRedoPtr;
@@ -9006,21 +9007,20 @@ CreateCheckPoint(int flags)
90069007
smgrpostckpt();
90079008

90089009
/*
9009-
* Delete old log files and recycle them
9010+
* Update the average distance between checkpoints if the prior checkpoint
9011+
* exists.
90109012
*/
90119013
if (PriorRedoPtr != InvalidXLogRecPtr)
9012-
{
9013-
XLogSegNo _logSegNo;
9014-
9015-
/* Update the average distance between checkpoints. */
90169014
UpdateCheckPointDistanceEstimate(RedoRecPtr - PriorRedoPtr);
90179015

9018-
/* Trim from the last checkpoint, not the last - 1 */
9019-
XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
9020-
KeepLogSeg(recptr, &_logSegNo);
9021-
_logSegNo--;
9022-
RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, recptr);
9023-
}
9016+
/*
9017+
* Delete old log files, those no longer needed for last checkpoint to
9018+
* prevent the disk holding the xlog from growing full.
9019+
*/
9020+
XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
9021+
KeepLogSeg(recptr, &_logSegNo);
9022+
_logSegNo--;
9023+
RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr);
90249024

90259025
/*
90269026
* Make more log segments if needed. (Do this after recycling old log
@@ -9186,6 +9186,11 @@ CreateRestartPoint(int flags)
91869186
XLogRecPtr lastCheckPointEndPtr;
91879187
CheckPoint lastCheckPoint;
91889188
XLogRecPtr PriorRedoPtr;
9189+
XLogRecPtr receivePtr;
9190+
XLogRecPtr replayPtr;
9191+
TimeLineID replayTLI;
9192+
XLogRecPtr endptr;
9193+
XLogSegNo _logSegNo;
91899194
TimestampTz xtime;
91909195

91919196
/*
@@ -9328,68 +9333,60 @@ CreateRestartPoint(int flags)
93289333
LWLockRelease(ControlFileLock);
93299334

93309335
/*
9331-
* Delete old log files (those no longer needed even for previous
9332-
* checkpoint/restartpoint) to prevent the disk holding the xlog from
9333-
* growing full.
9336+
* Update the average distance between checkpoints/restartpoints if the
9337+
* prior checkpoint exists.
93349338
*/
93359339
if (PriorRedoPtr != InvalidXLogRecPtr)
9336-
{
9337-
XLogRecPtr receivePtr;
9338-
XLogRecPtr replayPtr;
9339-
TimeLineID replayTLI;
9340-
XLogRecPtr endptr;
9341-
XLogSegNo _logSegNo;
9342-
9343-
/* Update the average distance between checkpoints/restartpoints. */
93449340
UpdateCheckPointDistanceEstimate(RedoRecPtr - PriorRedoPtr);
93459341

9346-
XLByteToSeg(PriorRedoPtr, _logSegNo, wal_segment_size);
9347-
9348-
/*
9349-
* Get the current end of xlog replayed or received, whichever is
9350-
* later.
9351-
*/
9352-
receivePtr = GetWalRcvWriteRecPtr(NULL, NULL);
9353-
replayPtr = GetXLogReplayRecPtr(&replayTLI);
9354-
endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
9342+
/*
9343+
* Delete old log files, those no longer needed for last restartpoint to
9344+
* prevent the disk holding the xlog from growing full.
9345+
*/
9346+
XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
93559347

9356-
KeepLogSeg(endptr, &_logSegNo);
9357-
_logSegNo--;
9348+
/*
9349+
* Retreat _logSegNo using the current end of xlog replayed or received,
9350+
* whichever is later.
9351+
*/
9352+
receivePtr = GetWalRcvWriteRecPtr(NULL, NULL);
9353+
replayPtr = GetXLogReplayRecPtr(&replayTLI);
9354+
endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
9355+
KeepLogSeg(endptr, &_logSegNo);
9356+
_logSegNo--;
93589357

9359-
/*
9360-
* Try to recycle segments on a useful timeline. If we've been
9361-
* promoted since the beginning of this restartpoint, use the new
9362-
* timeline chosen at end of recovery (RecoveryInProgress() sets
9363-
* ThisTimeLineID in that case). If we're still in recovery, use the
9364-
* timeline we're currently replaying.
9365-
*
9366-
* There is no guarantee that the WAL segments will be useful on the
9367-
* current timeline; if recovery proceeds to a new timeline right
9368-
* after this, the pre-allocated WAL segments on this timeline will
9369-
* not be used, and will go wasted until recycled on the next
9370-
* restartpoint. We'll live with that.
9371-
*/
9372-
if (RecoveryInProgress())
9373-
ThisTimeLineID = replayTLI;
9358+
/*
9359+
* Try to recycle segments on a useful timeline. If we've been promoted
9360+
* since the beginning of this restartpoint, use the new timeline chosen
9361+
* at end of recovery (RecoveryInProgress() sets ThisTimeLineID in that
9362+
* case). If we're still in recovery, use the timeline we're currently
9363+
* replaying.
9364+
*
9365+
* There is no guarantee that the WAL segments will be useful on the
9366+
* current timeline; if recovery proceeds to a new timeline right after
9367+
* this, the pre-allocated WAL segments on this timeline will not be used,
9368+
* and will go wasted until recycled on the next restartpoint. We'll live
9369+
* with that.
9370+
*/
9371+
if (RecoveryInProgress())
9372+
ThisTimeLineID = replayTLI;
93749373

9375-
RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, endptr);
9374+
RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr);
93769375

9377-
/*
9378-
* Make more log segments if needed. (Do this after recycling old log
9379-
* segments, since that may supply some of the needed files.)
9380-
*/
9381-
PreallocXlogFiles(endptr);
9376+
/*
9377+
* Make more log segments if needed. (Do this after recycling old log
9378+
* segments, since that may supply some of the needed files.)
9379+
*/
9380+
PreallocXlogFiles(endptr);
93829381

9383-
/*
9384-
* ThisTimeLineID is normally not set when we're still in recovery.
9385-
* However, recycling/preallocating segments above needed
9386-
* ThisTimeLineID to determine which timeline to install the segments
9387-
* on. Reset it now, to restore the normal state of affairs for
9388-
* debugging purposes.
9389-
*/
9390-
if (RecoveryInProgress())
9391-
ThisTimeLineID = 0;
9392-
}
9382+
/*
9383+
* ThisTimeLineID is normally not set when we're still in recovery.
9384+
* However, recycling/preallocating segments above needed ThisTimeLineID
9385+
* to determine which timeline to install the segments on. Reset it now,
9386+
* to restore the normal state of affairs for debugging purposes.
9387+
*/
9388+
if (RecoveryInProgress())
9389+
ThisTimeLineID = 0;
93939390

93949391
/*
93959392
* Truncate pg_subtrans if possible. We can throw away all data before

0 commit comments

Comments
 (0)