diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 335b4a573d..493f1db7b9 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -888,8 +888,8 @@ static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr); static void XLogFileClose(void); static void PreallocXlogFiles(XLogRecPtr endptr); static void RemoveTempXlogFiles(void); -static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr); -static void RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr); +static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr RedoRecPtr, XLogRecPtr endptr); +static void RemoveXlogFile(const char *segname, XLogRecPtr RedoRecPtr, XLogRecPtr endptr); static void UpdateLastRemovedPtr(char *filename); static void ValidateXLOGDirectoryStructure(void); static void CleanupBackupHistory(void); @@ -2287,7 +2287,7 @@ assign_checkpoint_completion_target(double newval, void *extra) * XLOG segments? Returns the highest segment that should be preallocated. */ static XLogSegNo -XLOGfileslop(XLogRecPtr PriorRedoPtr) +XLOGfileslop(XLogRecPtr RedoRecPtr) { XLogSegNo minSegNo; XLogSegNo maxSegNo; @@ -2299,9 +2299,9 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr) * correspond to. Always recycle enough segments to meet the minimum, and * remove enough segments to stay below the maximum. */ - minSegNo = PriorRedoPtr / wal_segment_size + + minSegNo = RedoRecPtr / wal_segment_size + ConvertToXSegs(min_wal_size_mb, wal_segment_size) - 1; - maxSegNo = PriorRedoPtr / wal_segment_size + + maxSegNo = RedoRecPtr / wal_segment_size + ConvertToXSegs(max_wal_size_mb, wal_segment_size) - 1; /* @@ -2316,7 +2316,7 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr) /* add 10% for good measure. */ distance *= 1.10; - recycleSegNo = (XLogSegNo) ceil(((double) PriorRedoPtr + distance) / + recycleSegNo = (XLogSegNo) ceil(((double) RedoRecPtr + distance) / wal_segment_size); if (recycleSegNo < minSegNo) @@ -3899,12 +3899,12 @@ RemoveTempXlogFiles(void) /* * Recycle or remove all log files older or equal to passed segno. * - * endptr is current (or recent) end of xlog, and PriorRedoRecPtr is the - * redo pointer of the previous checkpoint. These are used to determine + * endptr is current (or recent) end of xlog, and RedoRecPtr is the + * redo pointer of the last checkpoint. These are used to determine * whether we want to recycle rather than delete no-longer-wanted log files. */ static void -RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr) +RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr RedoRecPtr, XLogRecPtr endptr) { DIR *xldir; struct dirent *xlde; @@ -3947,7 +3947,7 @@ RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr) /* Update the last removed location in shared memory first */ UpdateLastRemovedPtr(xlde->d_name); - RemoveXlogFile(xlde->d_name, PriorRedoPtr, endptr); + RemoveXlogFile(xlde->d_name, RedoRecPtr, endptr); } } } @@ -4021,14 +4021,14 @@ RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI) /* * Recycle or remove a log file that's no longer needed. * - * endptr is current (or recent) end of xlog, and PriorRedoRecPtr is the - * redo pointer of the previous checkpoint. These are used to determine + * endptr is current (or recent) end of xlog, and RedoRecPtr is the + * redo pointer of the last checkpoint. These are used to determine * whether we want to recycle rather than delete no-longer-wanted log files. - * If PriorRedoRecPtr is not known, pass invalid, and the function will - * recycle, somewhat arbitrarily, 10 future segments. + * If RedoRecPtr is not known, pass invalid, and the function will recycle, + * somewhat arbitrarily, 10 future segments. */ static void -RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr) +RemoveXlogFile(const char *segname, XLogRecPtr RedoRecPtr, XLogRecPtr endptr) { char path[MAXPGPATH]; #ifdef WIN32 @@ -4042,10 +4042,10 @@ RemoveXlogFile(const char *segname, XLogRecPtr PriorRedoPtr, XLogRecPtr endptr) * Initialize info about where to try to recycle to. */ XLByteToSeg(endptr, endlogSegNo, wal_segment_size); - if (PriorRedoPtr == InvalidXLogRecPtr) + if (RedoRecPtr == InvalidXLogRecPtr) recycleSegNo = endlogSegNo + 10; else - recycleSegNo = XLOGfileslop(PriorRedoPtr); + recycleSegNo = XLOGfileslop(RedoRecPtr); snprintf(path, MAXPGPATH, XLOGDIR "/%s", segname); @@ -8706,6 +8706,7 @@ CreateCheckPoint(int flags) bool shutdown; CheckPoint checkPoint; XLogRecPtr recptr; + XLogSegNo _logSegNo; XLogCtlInsert *Insert = &XLogCtl->Insert; uint32 freespace; XLogRecPtr PriorRedoPtr; @@ -9073,21 +9074,20 @@ CreateCheckPoint(int flags) smgrpostckpt(); /* - * Delete old log files and recycle them + * Update the average distance between checkpoints if the prior checkpoint + * exists. */ if (PriorRedoPtr != InvalidXLogRecPtr) - { - XLogSegNo _logSegNo; - - /* Update the average distance between checkpoints. */ UpdateCheckPointDistanceEstimate(RedoRecPtr - PriorRedoPtr); - /* Trim from the last checkpoint, not the last - 1 */ - XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size); - KeepLogSeg(recptr, &_logSegNo); - _logSegNo--; - RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, recptr); - } + /* + * Delete old log files, those no longer needed for last checkpoint to + * prevent the disk holding the xlog from growing full. + */ + XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size); + KeepLogSeg(recptr, &_logSegNo); + _logSegNo--; + RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr); /* * Make more log segments if needed. (Do this after recycling old log @@ -9253,6 +9253,11 @@ CreateRestartPoint(int flags) XLogRecPtr lastCheckPointEndPtr; CheckPoint lastCheckPoint; XLogRecPtr PriorRedoPtr; + XLogRecPtr receivePtr; + XLogRecPtr replayPtr; + TimeLineID replayTLI; + XLogRecPtr endptr; + XLogSegNo _logSegNo; TimestampTz xtime; /* @@ -9395,68 +9400,60 @@ CreateRestartPoint(int flags) LWLockRelease(ControlFileLock); /* - * Delete old log files (those no longer needed even for previous - * checkpoint/restartpoint) to prevent the disk holding the xlog from - * growing full. + * Update the average distance between checkpoints/restartpoints if the + * prior checkpoint exists. */ if (PriorRedoPtr != InvalidXLogRecPtr) - { - XLogRecPtr receivePtr; - XLogRecPtr replayPtr; - TimeLineID replayTLI; - XLogRecPtr endptr; - XLogSegNo _logSegNo; - - /* Update the average distance between checkpoints/restartpoints. */ UpdateCheckPointDistanceEstimate(RedoRecPtr - PriorRedoPtr); - XLByteToSeg(PriorRedoPtr, _logSegNo, wal_segment_size); + /* + * Delete old log files, those no longer needed for last restartpoint to + * prevent the disk holding the xlog from growing full. + */ + XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size); - /* - * Get the current end of xlog replayed or received, whichever is - * later. - */ - receivePtr = GetWalRcvWriteRecPtr(NULL, NULL); - replayPtr = GetXLogReplayRecPtr(&replayTLI); - endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr; + /* + * Retreat _logSegNo using the current end of xlog replayed or received, + * whichever is later. + */ + receivePtr = GetWalRcvWriteRecPtr(NULL, NULL); + replayPtr = GetXLogReplayRecPtr(&replayTLI); + endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr; + KeepLogSeg(endptr, &_logSegNo); + _logSegNo--; - KeepLogSeg(endptr, &_logSegNo); - _logSegNo--; + /* + * Try to recycle segments on a useful timeline. If we've been promoted + * since the beginning of this restartpoint, use the new timeline chosen + * at end of recovery (RecoveryInProgress() sets ThisTimeLineID in that + * case). If we're still in recovery, use the timeline we're currently + * replaying. + * + * There is no guarantee that the WAL segments will be useful on the + * current timeline; if recovery proceeds to a new timeline right after + * this, the pre-allocated WAL segments on this timeline will not be used, + * and will go wasted until recycled on the next restartpoint. We'll live + * with that. + */ + if (RecoveryInProgress()) + ThisTimeLineID = replayTLI; - /* - * Try to recycle segments on a useful timeline. If we've been - * promoted since the beginning of this restartpoint, use the new - * timeline chosen at end of recovery (RecoveryInProgress() sets - * ThisTimeLineID in that case). If we're still in recovery, use the - * timeline we're currently replaying. - * - * There is no guarantee that the WAL segments will be useful on the - * current timeline; if recovery proceeds to a new timeline right - * after this, the pre-allocated WAL segments on this timeline will - * not be used, and will go wasted until recycled on the next - * restartpoint. We'll live with that. - */ - if (RecoveryInProgress()) - ThisTimeLineID = replayTLI; + RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr); - RemoveOldXlogFiles(_logSegNo, PriorRedoPtr, endptr); + /* + * Make more log segments if needed. (Do this after recycling old log + * segments, since that may supply some of the needed files.) + */ + PreallocXlogFiles(endptr); - /* - * Make more log segments if needed. (Do this after recycling old log - * segments, since that may supply some of the needed files.) - */ - PreallocXlogFiles(endptr); - - /* - * ThisTimeLineID is normally not set when we're still in recovery. - * However, recycling/preallocating segments above needed - * ThisTimeLineID to determine which timeline to install the segments - * on. Reset it now, to restore the normal state of affairs for - * debugging purposes. - */ - if (RecoveryInProgress()) - ThisTimeLineID = 0; - } + /* + * ThisTimeLineID is normally not set when we're still in recovery. + * However, recycling/preallocating segments above needed ThisTimeLineID + * to determine which timeline to install the segments on. Reset it now, + * to restore the normal state of affairs for debugging purposes. + */ + if (RecoveryInProgress()) + ThisTimeLineID = 0; /* * Truncate pg_subtrans if possible. We can throw away all data before