]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Reset lastOverflowedXid on standby when needed
authorAlexander Korotkov <akorotkov@postgresql.org>
Sat, 6 Nov 2021 15:31:21 +0000 (18:31 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Sat, 6 Nov 2021 15:34:31 +0000 (18:34 +0300)
Currently, lastOverflowedXid is never reset.  It's just adjusted on new
transactions known to be overflowed.  But if there are no overflowed
transactions for a long time, snapshots could be mistakenly marked as
suboverflowed due to wraparound.

This commit fixes this issue by resetting lastOverflowedXid when needed
altogether with KnownAssignedXids.

Backpatch to all supported versions.

Reported-by: Stan Hu
Discussion: https://postgr.es/m/CAMBWrQ%3DFp5UAsU_nATY7EMY7NHczG4-DTDU%3DmCvBQZAQ6wa2xQ%40mail.gmail.com
Author: Kyotaro Horiguchi, Alexander Korotkov
Reviewed-by: Stan Hu, Simon Riggs, Nikolay Samokhvalov, Andrey Borodin, Dmitry Dolgov
src/backend/storage/ipc/procarray.c

index 96bbd7296c3051390edd7012348e0e2ccd03e0dd..668c5f5ea6adbbc2ac87fbd864ca8d3e0ed60682 100644 (file)
@@ -3289,24 +3289,41 @@ ExpireTreeKnownAssignedTransactionIds(TransactionId xid, int nsubxids,
 
 /*
  * ExpireAllKnownAssignedTransactionIds
- *             Remove all entries in KnownAssignedXids
+ *             Remove all entries in KnownAssignedXids and reset lastOverflowedXid.
  */
 void
 ExpireAllKnownAssignedTransactionIds(void)
 {
        LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
        KnownAssignedXidsRemovePreceding(InvalidTransactionId);
+
+       /*
+        * Reset lastOverflowedXid.  Currently, lastOverflowedXid has no use after
+        * the call of this function.  But do this for unification with what
+        * ExpireOldKnownAssignedTransactionIds() do.
+        */
+       procArray->lastOverflowedXid = InvalidTransactionId;
        LWLockRelease(ProcArrayLock);
 }
 
 /*
  * ExpireOldKnownAssignedTransactionIds
- *             Remove KnownAssignedXids entries preceding the given XID
+ *             Remove KnownAssignedXids entries preceding the given XID and
+ *             potentially reset lastOverflowedXid.
  */
 void
 ExpireOldKnownAssignedTransactionIds(TransactionId xid)
 {
        LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
+       /*
+        * Reset lastOverflowedXid if we know all transactions that have been
+        * possibly running are being gone.  Not doing so could cause an incorrect
+        * lastOverflowedXid value, which makes extra snapshots be marked as
+        * suboverflowed.
+        */
+       if (TransactionIdPrecedes(procArray->lastOverflowedXid, xid))
+               procArray->lastOverflowedXid = InvalidTransactionId;
        KnownAssignedXidsRemovePreceding(xid);
        LWLockRelease(ProcArrayLock);
 }