From ea6c90033a7901155d29bfdd0426f29e2171cff4 Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Thu, 5 Oct 2023 23:15:40 +0000 Subject: [PATCH 1/1] Fix false "apparent wraparound" detected in pg_serial It is possible that a pg_serial tailXid is ahead of the HeadXid. Currently, this appears as "wraparound" to SimpleLruTruncate, which called during Checkpoint. This patch fixes this scenario by adding a condition in CheckPointPredicate which considers the SLRU no longer needed if the tailXID has advanced beyond the headXid. Discussion: https://www.postgresql.org/message-id/flat/755E19CA-D02C-4A4C-80D3-74F775410C48%40amazon.com --- src/backend/storage/lmgr/predicate.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 1af41213b4..f4b9d192b5 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1005,6 +1005,7 @@ void CheckPointPredicate(void) { int tailPage; + int truncateCutoff; LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE); @@ -1015,10 +1016,22 @@ CheckPointPredicate(void) return; } + tailPage = SerialPage(serialControl->tailXid); + if (TransactionIdIsValid(serialControl->tailXid)) { - /* We can truncate the SLRU up to the page containing tailXid */ - tailPage = SerialPage(serialControl->tailXid); + /* + * It is possible for the tailXid to be ahead of the headXid. This + * occurs if we checkpoint while there are in progress serializable + * transaction(s) advancing the tail; but we are yet to summarize the + * transactions. In this case, we cutoff up to the headPage and the + * next summary will advance the headXid. + */ + if (!SerialPagePrecedesLogically(tailPage, serialControl->headPage)) + truncateCutoff = serialControl->headPage; + else + /* We can truncate the SLRU up to the page containing tailXid */ + truncateCutoff = tailPage; } else { @@ -1051,14 +1064,14 @@ CheckPointPredicate(void) * transaction instigating the summarize fails in * SimpleLruReadPage(). */ - tailPage = serialControl->headPage; + truncateCutoff = serialControl->headPage; serialControl->headPage = -1; } LWLockRelease(SerialSLRULock); /* Truncate away pages that are no longer required */ - SimpleLruTruncate(SerialSlruCtl, tailPage); + SimpleLruTruncate(SerialSlruCtl, truncateCutoff); /* * Write dirty SLRU pages to disk -- 2.40.1