1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

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
This commit is contained in:
Heikki Linnakangas
2026-09-16 14:52:12 +03:00
parent a4f18fd8f2
commit fcc0e27f45

View File

@@ -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)));