On 28/08/2026 02:17, Noah Misch wrote:
commit bd8d9c9 wrote:
Commit: Heikki Linnakangas <[email protected]>
CommitDate: Tue Dec 9 13:53:03 2025 +0200
Widen MultiXactOffset to 64 bits
--- a/src/bin/pg_upgrade/pg_upgrade.c
+++ b/src/bin/pg_upgrade/pg_upgrade.c
+ nxtmulti = old_cluster.controldata.chkpnt_nxtmulti;
+ if (old_cluster.controldata.cat_ver >=
MULTIXACT_FORMATCHANGE_CAT_VER)
+ {
+ /* Versions 9.3 - 18: convert all multixids */
+ oldstMulti = old_cluster.controldata.chkpnt_oldstMulti;
If a cluster's upgrade history includes an upgrade from 9.3 to early 9.4, it
may have a wrong value here. Specifically, upgrades done before a61daa14
(2014-07 commit) have that hazard. We still have backend code to detect such
cases and reduce damage:
ereport(LOG,
(errmsg("cannot truncate up to MultiXact %u because
it does not exist on disk, skipping truncation",
newOldestMulti)));
However, the pg_upgrade side from the v19 commit lacks such protection. If
heap tuples still reference older multixacts than the faulty control data
suggests, pg_upgrade will copy too small a range, making affected tuples
unreadable.
Thanks, I'll look into this. My first reaction is that I think if
oldstMulti is incorrectly too old, the upgrade will fail because the
conversion routine will fail to find it. If it's too new, i.e. "in the
future", it will also fail to find it.
The third possibility is that the bogus oldstMulti value is within the
range of the "real" range. That can happen if multixid wraparound had
already happened before the (broken) 9.3 -> 9.4 upgrade. In that case,
even if the multixids are still readable on disk, you're one vacuum away
from truncating them. In other words, the damage has already been done,
or could be done at any minute. That's the scenario for which the commit
message 78db307bb2 says "this mechanism cannot save us".
But I'll do some testing of that. Let's ensure that the error message
makes sense at the very least.
I also had Opus 4.8 look for defects in this change and write test cases. It
didn't find the above problem, but it had other findings. I'm attaching the
full report. I recommend fixing at least these before release:
+| 5 | `resetwal-nextmxoff-zero` | `src/bin/pg_resetwal/pg_resetwal.c:703`, and `-O` with
no zero check at 297-307 | `pg_resetwal -f` (or `-O 0`) leaves `nextMultiOffset = 0`, the
reserved "invalid offset"; first multixact created afterwards is permanently
unreadable: `ERROR: MultiXact 1 has invalid offset` | Yes —
`src/test/modules/test_slru/t/003_multixact_offset.pl` |
This was already fixed in commit 2cad308cb8.
+| 7 | `members-truncation-apparent-wraparound` |
`src/backend/access/transam/multixact.c:2642-2647` | When `nextOffset` lands on a members
page boundary, truncation logs `could not truncate directory
"pg_multixact/members": apparent wraparound` (impossible for a 64-bit counter)
and reclaims nothing | Yes — `003_multixact_offset.pl` |
Ok, I'll look into this one, and the other ones that might not be fixed yet.
- Heikki