@ -650,7 +650,8 @@ static XLogRecPtr CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn,
XLogRecPtr pagePtr ,
TimeLineID newTLI ) ;
static void CheckPointGuts ( XLogRecPtr checkPointRedo , int flags ) ;
static void KeepLogSeg ( XLogRecPtr recptr , XLogSegNo * logSegNo ) ;
static void KeepLogSeg ( XLogRecPtr recptr , XLogRecPtr slotsMinLSN ,
XLogSegNo * logSegNo ) ;
static XLogRecPtr XLogGetReplicationSlotMinimumLSN ( void ) ;
static void AdvanceXLInsertBuffer ( XLogRecPtr upto , TimeLineID tli ,
@ -6492,6 +6493,7 @@ CreateCheckPoint(int flags)
VirtualTransactionId * vxids ;
int nvxids ;
int oldXLogAllowed = 0 ;
XLogRecPtr slotsMinReqLSN ;
/*
* An end - of - recovery checkpoint is really a shutdown checkpoint , just
@ -6693,6 +6695,15 @@ CreateCheckPoint(int flags)
*/
END_CRIT_SECTION ( ) ;
/*
* Get the current minimum LSN to be used later in the WAL segment
* cleanup . We may clean up only WAL segments , which are not needed
* according to synchronized LSNs of replication slots . The slot ' s LSN
* might be advanced concurrently , so we call this before
* CheckPointReplicationSlots ( ) synchronizes replication slots .
*/
slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ( ) ;
/*
* In some cases there are groups of actions that must all occur on one
* side or the other of a checkpoint record . Before flushing the
@ -6858,17 +6869,25 @@ CreateCheckPoint(int flags)
* prevent the disk holding the xlog from growing full .
*/
XLByteToSeg ( RedoRecPtr , _logSegNo , wal_segment_size ) ;
KeepLogSeg ( recptr , & _logSegNo ) ;
KeepLogSeg ( recptr , slotsMinReqLSN , & _logSegNo ) ;
if ( InvalidateObsoleteReplicationSlots ( RS_INVAL_WAL_REMOVED ,
_logSegNo , InvalidOid ,
InvalidTransactionId ) )
{
/*
* Recalculate the current minimum LSN to be used in the WAL segment
* cleanup . Then , we must synchronize the replication slots again in
* order to make this LSN safe to use .
*/
slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ( ) ;
CheckPointReplicationSlots ( ) ;
/*
* Some slots have been invalidated ; recalculate the old - segment
* horizon , starting again from RedoRecPtr .
*/
XLByteToSeg ( RedoRecPtr , _logSegNo , wal_segment_size ) ;
KeepLogSeg ( recptr , & _logSegNo ) ;
KeepLogSeg ( recptr , slotsMinReqLSN , & _logSegNo ) ;
}
_logSegNo - - ;
RemoveOldXlogFiles ( _logSegNo , RedoRecPtr , recptr ,
@ -7140,6 +7159,7 @@ CreateRestartPoint(int flags)
XLogRecPtr endptr ;
XLogSegNo _logSegNo ;
TimestampTz xtime ;
XLogRecPtr slotsMinReqLSN ;
/* Concurrent checkpoint/restartpoint cannot happen */
Assert ( ! IsUnderPostmaster | | MyBackendType = = B_CHECKPOINTER ) ;
@ -7222,6 +7242,15 @@ CreateRestartPoint(int flags)
MemSet ( & CheckpointStats , 0 , sizeof ( CheckpointStats ) ) ;
CheckpointStats . ckpt_start_t = GetCurrentTimestamp ( ) ;
/*
* Get the current minimum LSN to be used later in the WAL segment
* cleanup . We may clean up only WAL segments , which are not needed
* according to synchronized LSNs of replication slots . The slot ' s LSN
* might be advanced concurrently , so we call this before
* CheckPointReplicationSlots ( ) synchronizes replication slots .
*/
slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ( ) ;
if ( log_checkpoints )
LogCheckpointStart ( flags , true ) ;
@ -7304,17 +7333,25 @@ CreateRestartPoint(int flags)
receivePtr = GetWalRcvFlushRecPtr ( NULL , NULL ) ;
replayPtr = GetXLogReplayRecPtr ( & replayTLI ) ;
endptr = ( receivePtr < replayPtr ) ? replayPtr : receivePtr ;
KeepLogSeg ( endptr , & _logSegNo ) ;
KeepLogSeg ( endptr , slotsMinReqLSN , & _logSegNo ) ;
if ( InvalidateObsoleteReplicationSlots ( RS_INVAL_WAL_REMOVED ,
_logSegNo , InvalidOid ,
InvalidTransactionId ) )
{
/*
* Recalculate the current minimum LSN to be used in the WAL segment
* cleanup . Then , we must synchronize the replication slots again in
* order to make this LSN safe to use .
*/
slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ( ) ;
CheckPointReplicationSlots ( ) ;
/*
* Some slots have been invalidated ; recalculate the old - segment
* horizon , starting again from RedoRecPtr .
*/
XLByteToSeg ( RedoRecPtr , _logSegNo , wal_segment_size ) ;
KeepLogSeg ( endptr , & _logSegNo ) ;
KeepLogSeg ( endptr , slotsMinReqLSN , & _logSegNo ) ;
}
_logSegNo - - ;
@ -7409,6 +7446,7 @@ GetWALAvailability(XLogRecPtr targetLSN)
XLogSegNo oldestSegMaxWalSize ; /* oldest segid kept by max_wal_size */
XLogSegNo oldestSlotSeg ; /* oldest segid kept by slot */
uint64 keepSegs ;
XLogRecPtr slotsMinReqLSN ;
/*
* slot does not reserve WAL . Either deactivated , or has never been active
@ -7422,8 +7460,9 @@ GetWALAvailability(XLogRecPtr targetLSN)
* oldestSlotSeg to the current segment .
*/
currpos = GetXLogWriteRecPtr ( ) ;
slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ( ) ;
XLByteToSeg ( currpos , oldestSlotSeg , wal_segment_size ) ;
KeepLogSeg ( currpos , & oldestSlotSeg ) ;
KeepLogSeg ( currpos , slotsMinReqLSN , & oldestSlotSeg ) ;
/*
* Find the oldest extant segment file . We get 1 until checkpoint removes
@ -7484,7 +7523,7 @@ GetWALAvailability(XLogRecPtr targetLSN)
* invalidation is optionally done here , instead .
*/
static void
KeepLogSeg ( XLogRecPtr recptr , XLogSegNo * logSegNo )
KeepLogSeg ( XLogRecPtr recptr , XLogRecPtr slotsMinReqLSN , XLog SegNo * logSegNo )
{
XLogSegNo currSegNo ;
XLogSegNo segno ;
@ -7497,7 +7536,7 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
* Calculate how many segments are kept by slots first , adjusting for
* max_slot_wal_keep_size .
*/
keep = XLogGetReplicationSlotMinimumLSN ( ) ;
keep = slotsMinReqLSN ;
if ( keep ! = InvalidXLogRecPtr & & keep < recptr )
{
XLByteToSeg ( keep , segno , wal_segment_size ) ;