On Thu, Sep 17, 2026 at 06:25:58PM +0300, Heikki Linnakangas wrote:
> On 16/09/2026 14:33, Heikki Linnakangas wrote:
> > 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.

Agreed, those cases fail cleanly.  No concerns on those.

> > The third possibility is that the bogus oldstMulti value is within the
> > range of the "real" range.

That's the only scenario I felt was at risk.  For example, the range of MXIDs
in tuple headers is [(unsigned)-100M,200M], but oldestMulti is 1.

> > 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.

Okay.  I briefly tried to verify how rapidly one can expect v18 to truncate
the SLRUs in this scenario, but I didn't get very far.  I will rely on your
analysis.  Thanks for studying it.

> With the attached patch, you get an error message crafted specifically for
> that case.
> 
> > Converting pg_multixact files                                 fatal
> > 
> > Segment file containing multixid 1 does not exist.
> > This can happen if an old version of pg_upgrade was used in the past
> > to upgrade the cluster from version 9.3 to 9.4. If that is the cause,
> > it can be fixed by running VACUUM FREEZE before upgrade.
> > Failure, exiting
> 
> I'm not sure this is worth committing though. How many clusters are there
> out there that have been pg_upgraded to version 9.3.0-9.3.4, and haven't
> since been running for long enough to fix the oldestMultiXid value? Having
> that error message seems pretty harmless too, but if you actually hit that
> case that the file is missing, it might actually be more likely that you've
> hit some other bug than that old pg_upgrade issue.

I wouldn't commit the more-specific error message.  If it did something for
the "third possibility", that might be different.  I think we can consider
closed the topic of how 9.3 upgrades interact with 64-bit MultiXactOffset.


Reply via email to