From 757483c3446dfd4566da32079d7ed45cf73ee0bc Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 7 Nov 2025 17:06:07 +0200 Subject: [PATCH 2/2] Fix truncation of multixid SLRUs at wraparound SetOffsetVacuumLimit() and TruncateMultiXact() have checks for MultiXactState->nextMXact == MultiXactState->oldestMultiXactId. However, those checks didn't work as intended at wraparound. When the last multixid before wraparound (UINT32_MAX) is consumed, MultiXactState->nextMXact is advanced to 0, but because 0 is not a valid multixid, all code that reads MultiXactState->nextMXact treats 0 as if the value was 1. Except for the checks in SetOffsetVacuumLimit() and TruncateMultiXact(). As a result, at exactly multixid wraparound, VACUUM would fail to truncate multixact SLRUs, or worse, it might truncate the offsets SLRU incorrectly. I think the incorrect truncation is possible if a new multixid is assigned concurrently just as vacuum reads the offsets SLRU. The failure to truncate is easier to reproduce, but less serious. Discussion: XXX --- src/backend/access/transam/multixact.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 9d5f130af7e..735486f9df7 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -2673,6 +2673,9 @@ SetOffsetVacuumLimit(bool is_startup) Assert(MultiXactState->finishedStartup); LWLockRelease(MultiXactGenLock); + if (nextMXact < FirstMultiXactId) + nextMXact = FirstMultiXactId; + /* * Determine the offset of the oldest multixact. Normally, we can read * the offset from the multixact itself, but there's an important special @@ -3075,6 +3078,9 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB) LWLockRelease(MultiXactGenLock); Assert(MultiXactIdIsValid(oldestMulti)); + if (nextMulti < FirstMultiXactId) + nextMulti = FirstMultiXactId; + /* * Make sure to only attempt truncation if there's values to truncate * away. In normal processing values shouldn't go backwards, but there's -- 2.47.3