@@ -650,7 +650,8 @@ static XLogRecPtr CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn,
650
650
XLogRecPtr pagePtr ,
651
651
TimeLineID newTLI );
652
652
static void CheckPointGuts (XLogRecPtr checkPointRedo , int flags );
653
- static void KeepLogSeg (XLogRecPtr recptr , XLogSegNo * logSegNo );
653
+ static void KeepLogSeg (XLogRecPtr recptr , XLogRecPtr slotsMinLSN ,
654
+ XLogSegNo * logSegNo );
654
655
static XLogRecPtr XLogGetReplicationSlotMinimumLSN (void );
655
656
656
657
static void AdvanceXLInsertBuffer (XLogRecPtr upto , TimeLineID tli ,
@@ -6492,6 +6493,7 @@ CreateCheckPoint(int flags)
6492
6493
VirtualTransactionId * vxids ;
6493
6494
int nvxids ;
6494
6495
int oldXLogAllowed = 0 ;
6496
+ XLogRecPtr slotsMinReqLSN ;
6495
6497
6496
6498
/*
6497
6499
* An end-of-recovery checkpoint is really a shutdown checkpoint, just
@@ -6693,6 +6695,15 @@ CreateCheckPoint(int flags)
6693
6695
*/
6694
6696
END_CRIT_SECTION ();
6695
6697
6698
+ /*
6699
+ * Get the current minimum LSN to be used later in the WAL segment
6700
+ * cleanup. We may clean up only WAL segments, which are not needed
6701
+ * according to synchronized LSNs of replication slots. The slot's LSN
6702
+ * might be advanced concurrently, so we call this before
6703
+ * CheckPointReplicationSlots() synchronizes replication slots.
6704
+ */
6705
+ slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ();
6706
+
6696
6707
/*
6697
6708
* In some cases there are groups of actions that must all occur on one
6698
6709
* side or the other of a checkpoint record. Before flushing the
@@ -6858,17 +6869,25 @@ CreateCheckPoint(int flags)
6858
6869
* prevent the disk holding the xlog from growing full.
6859
6870
*/
6860
6871
XLByteToSeg (RedoRecPtr , _logSegNo , wal_segment_size );
6861
- KeepLogSeg (recptr , & _logSegNo );
6872
+ KeepLogSeg (recptr , slotsMinReqLSN , & _logSegNo );
6862
6873
if (InvalidateObsoleteReplicationSlots (RS_INVAL_WAL_REMOVED ,
6863
6874
_logSegNo , InvalidOid ,
6864
6875
InvalidTransactionId ))
6865
6876
{
6877
+ /*
6878
+ * Recalculate the current minimum LSN to be used in the WAL segment
6879
+ * cleanup. Then, we must synchronize the replication slots again in
6880
+ * order to make this LSN safe to use.
6881
+ */
6882
+ slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ();
6883
+ CheckPointReplicationSlots ();
6884
+
6866
6885
/*
6867
6886
* Some slots have been invalidated; recalculate the old-segment
6868
6887
* horizon, starting again from RedoRecPtr.
6869
6888
*/
6870
6889
XLByteToSeg (RedoRecPtr , _logSegNo , wal_segment_size );
6871
- KeepLogSeg (recptr , & _logSegNo );
6890
+ KeepLogSeg (recptr , slotsMinReqLSN , & _logSegNo );
6872
6891
}
6873
6892
_logSegNo -- ;
6874
6893
RemoveOldXlogFiles (_logSegNo , RedoRecPtr , recptr ,
@@ -7140,6 +7159,7 @@ CreateRestartPoint(int flags)
7140
7159
XLogRecPtr endptr ;
7141
7160
XLogSegNo _logSegNo ;
7142
7161
TimestampTz xtime ;
7162
+ XLogRecPtr slotsMinReqLSN ;
7143
7163
7144
7164
/* Concurrent checkpoint/restartpoint cannot happen */
7145
7165
Assert (!IsUnderPostmaster || MyBackendType == B_CHECKPOINTER );
@@ -7222,6 +7242,15 @@ CreateRestartPoint(int flags)
7222
7242
MemSet (& CheckpointStats , 0 , sizeof (CheckpointStats ));
7223
7243
CheckpointStats .ckpt_start_t = GetCurrentTimestamp ();
7224
7244
7245
+ /*
7246
+ * Get the current minimum LSN to be used later in the WAL segment
7247
+ * cleanup. We may clean up only WAL segments, which are not needed
7248
+ * according to synchronized LSNs of replication slots. The slot's LSN
7249
+ * might be advanced concurrently, so we call this before
7250
+ * CheckPointReplicationSlots() synchronizes replication slots.
7251
+ */
7252
+ slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ();
7253
+
7225
7254
if (log_checkpoints )
7226
7255
LogCheckpointStart (flags , true);
7227
7256
@@ -7304,17 +7333,25 @@ CreateRestartPoint(int flags)
7304
7333
receivePtr = GetWalRcvFlushRecPtr (NULL , NULL );
7305
7334
replayPtr = GetXLogReplayRecPtr (& replayTLI );
7306
7335
endptr = (receivePtr < replayPtr ) ? replayPtr : receivePtr ;
7307
- KeepLogSeg (endptr , & _logSegNo );
7336
+ KeepLogSeg (endptr , slotsMinReqLSN , & _logSegNo );
7308
7337
if (InvalidateObsoleteReplicationSlots (RS_INVAL_WAL_REMOVED ,
7309
7338
_logSegNo , InvalidOid ,
7310
7339
InvalidTransactionId ))
7311
7340
{
7341
+ /*
7342
+ * Recalculate the current minimum LSN to be used in the WAL segment
7343
+ * cleanup. Then, we must synchronize the replication slots again in
7344
+ * order to make this LSN safe to use.
7345
+ */
7346
+ slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ();
7347
+ CheckPointReplicationSlots ();
7348
+
7312
7349
/*
7313
7350
* Some slots have been invalidated; recalculate the old-segment
7314
7351
* horizon, starting again from RedoRecPtr.
7315
7352
*/
7316
7353
XLByteToSeg (RedoRecPtr , _logSegNo , wal_segment_size );
7317
- KeepLogSeg (endptr , & _logSegNo );
7354
+ KeepLogSeg (endptr , slotsMinReqLSN , & _logSegNo );
7318
7355
}
7319
7356
_logSegNo -- ;
7320
7357
@@ -7409,6 +7446,7 @@ GetWALAvailability(XLogRecPtr targetLSN)
7409
7446
XLogSegNo oldestSegMaxWalSize ; /* oldest segid kept by max_wal_size */
7410
7447
XLogSegNo oldestSlotSeg ; /* oldest segid kept by slot */
7411
7448
uint64 keepSegs ;
7449
+ XLogRecPtr slotsMinReqLSN ;
7412
7450
7413
7451
/*
7414
7452
* slot does not reserve WAL. Either deactivated, or has never been active
@@ -7422,8 +7460,9 @@ GetWALAvailability(XLogRecPtr targetLSN)
7422
7460
* oldestSlotSeg to the current segment.
7423
7461
*/
7424
7462
currpos = GetXLogWriteRecPtr ();
7463
+ slotsMinReqLSN = XLogGetReplicationSlotMinimumLSN ();
7425
7464
XLByteToSeg (currpos , oldestSlotSeg , wal_segment_size );
7426
- KeepLogSeg (currpos , & oldestSlotSeg );
7465
+ KeepLogSeg (currpos , slotsMinReqLSN , & oldestSlotSeg );
7427
7466
7428
7467
/*
7429
7468
* Find the oldest extant segment file. We get 1 until checkpoint removes
@@ -7484,7 +7523,7 @@ GetWALAvailability(XLogRecPtr targetLSN)
7484
7523
* invalidation is optionally done here, instead.
7485
7524
*/
7486
7525
static void
7487
- KeepLogSeg (XLogRecPtr recptr , XLogSegNo * logSegNo )
7526
+ KeepLogSeg (XLogRecPtr recptr , XLogRecPtr slotsMinReqLSN , XLogSegNo * logSegNo )
7488
7527
{
7489
7528
XLogSegNo currSegNo ;
7490
7529
XLogSegNo segno ;
@@ -7497,7 +7536,7 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
7497
7536
* Calculate how many segments are kept by slots first, adjusting for
7498
7537
* max_slot_wal_keep_size.
7499
7538
*/
7500
- keep = XLogGetReplicationSlotMinimumLSN () ;
7539
+ keep = slotsMinReqLSN ;
7501
7540
if (keep != InvalidXLogRecPtr && keep < recptr )
7502
7541
{
7503
7542
XLByteToSeg (keep , segno , wal_segment_size );
0 commit comments