summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas2026-09-16 11:52:12 +0000
committerHeikki Linnakangas2026-09-16 11:53:50 +0000
commitd8408e8d6823036bb88310b36eed8d9607220847 (patch)
tree8106361b78558aebfd62aedebc1fb45d3a77c2d9
parent0d5621890583bf64679ad4e4960c850732313472 (diff)
Fix multixact members truncation at page boundary
Like in PerformOffsetsTruncation() and e.g. in TruncateSUBTRANS(), need to step back to previous page at page boundary, to avoid passing a cutoff page to SimpleLruTruncate() that hasn't been created yet. Otherwise you can get a bogus 'LOG: could not truncate directory "pg_multixact/members": apparent wraparound' message in the log. Reported-by: Noah Misch <noah@leadboat.com> Discussion: https://www.postgresql.org/message-id/20260827231757.78.noahmisch@microsoft.com Backpatch-through: 19
-rw-r--r--src/backend/access/transam/multixact.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 424516dc106..0dbb072ce44 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -2642,8 +2642,16 @@ MultiXactMemberFreezeThreshold(void)
static void
PerformMembersTruncation(MultiXactOffset newOldestOffset)
{
+ /*
+ * We step back one entry to avoid passing a cutoff page that hasn't been
+ * created yet in the rare case that oldestOffset would be the first item
+ * on a page and oldestOffset == nextOffset. In that case, if we didn't
+ * subtract one, we'd trigger SimpleLruTruncate's wraparound detection.
+ */
+ if (newOldestOffset <= 1)
+ return;
SimpleLruTruncate(MultiXactMemberCtl,
- MXOffsetToMemberPage(newOldestOffset));
+ MXOffsetToMemberPage(newOldestOffset - 1));
}
/*
@@ -2653,11 +2661,8 @@ static void
PerformOffsetsTruncation(MultiXactId newOldestMulti)
{
/*
- * We step back one multixact to avoid passing a cutoff page that hasn't
- * been created yet in the rare case that oldestMulti would be the first
- * item on a page and oldestMulti == nextMulti. In that case, if we
- * didn't subtract one, we'd trigger SimpleLruTruncate's wraparound
- * detection.
+ * Like in PerformMembersTruncation(), step back one entry to avoid
+ * passing a cutoff page that hasn't been created yet.
*/
SimpleLruTruncate(MultiXactOffsetCtl,
MultiXactIdToOffsetPage(PreviousMultiXactId(newOldestMulti)));