From 924c63daf1ceb9d796e18567afa6904cbe672a00 Mon Sep 17 00:00:00 2001 From: Maxim Orlov Date: Fri, 20 Jun 2025 17:21:08 +0300 Subject: [PATCH v2 1/1] Fix the mxid and mxoff wraparound issues in pg_upgrade. Per bags: - BUG #18863: Multixact wraparound and pg_resetwal error "multitransaction ID (-m) must not be 0" - BUG #18865: pg_resetwal error: multitransaction offset (-O) must not be -1 --- src/bin/pg_resetwal/pg_resetwal.c | 18 +++++++++--------- src/bin/pg_upgrade/pg_upgrade.c | 11 ++++++++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c index a89d72fc5cf..3d61f025c5e 100644 --- a/src/bin/pg_resetwal/pg_resetwal.c +++ b/src/bin/pg_resetwal/pg_resetwal.c @@ -70,8 +70,10 @@ static TransactionId set_xid = 0; static TransactionId set_oldest_commit_ts_xid = 0; static TransactionId set_newest_commit_ts_xid = 0; static Oid set_oid = 0; +static bool mxid_given = false; static MultiXactId set_mxid = 0; -static MultiXactOffset set_mxoff = (MultiXactOffset) -1; +static bool mxoff_given = false; +static MultiXactOffset set_mxoff = 0; static TimeLineID minXlogTli = 0; static XLogSegNo minXlogSegNo = 0; static int WalSegSz; @@ -246,6 +248,7 @@ main(int argc, char *argv[]) pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1); } + mxid_given = true; set_oldestmxid = strtoul(endptr + 1, &endptr2, 0); if (endptr2 == endptr + 1 || *endptr2 != '\0' || errno != 0) @@ -254,8 +257,6 @@ main(int argc, char *argv[]) pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1); } - if (set_mxid == 0) - pg_fatal("multitransaction ID (-m) must not be 0"); /* * XXX It'd be nice to have more sanity checks here, e.g. so @@ -274,8 +275,7 @@ main(int argc, char *argv[]) pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1); } - if (set_mxoff == -1) - pg_fatal("multitransaction offset (-O) must not be -1"); + mxoff_given = true; break; case 'l': @@ -454,7 +454,7 @@ main(int argc, char *argv[]) if (set_oid != 0) ControlFile.checkPointCopy.nextOid = set_oid; - if (set_mxid != 0) + if (mxid_given) { ControlFile.checkPointCopy.nextMulti = set_mxid; @@ -464,7 +464,7 @@ main(int argc, char *argv[]) ControlFile.checkPointCopy.oldestMultiDB = InvalidOid; } - if (set_mxoff != -1) + if (mxoff_given) ControlFile.checkPointCopy.nextMultiOffset = set_mxoff; if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID) @@ -805,7 +805,7 @@ PrintNewControlValues(void) newXlogSegNo, WalSegSz); printf(_("First log segment after reset: %s\n"), fname); - if (set_mxid != 0) + if (mxid_given) { printf(_("NextMultiXactId: %u\n"), ControlFile.checkPointCopy.nextMulti); @@ -815,7 +815,7 @@ PrintNewControlValues(void) ControlFile.checkPointCopy.oldestMultiDB); } - if (set_mxoff != -1) + if (mxoff_given) { printf(_("NextMultiOffset: %u\n"), ControlFile.checkPointCopy.nextMultiOffset); diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 490e98fa26f..2a317e59108 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -816,6 +816,15 @@ copy_xact_xlog_xid(void) if (old_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER && new_cluster.controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) { + uint32 old_chkpnt_nxtmulti = old_cluster.controldata.chkpnt_nxtmulti; + + /* + * Beware of the possibility that chkpnt_nxtmulti is in the + * wrapped-around state in old cluster. + */ + if (old_chkpnt_nxtmulti == 0) + old_chkpnt_nxtmulti = 1; /* FirstMultiXactId */ + copy_subdir_files("pg_multixact/offsets", "pg_multixact/offsets"); copy_subdir_files("pg_multixact/members", "pg_multixact/members"); @@ -829,7 +838,7 @@ copy_xact_xlog_xid(void) "\"%s/pg_resetwal\" -O %u -m %u,%u \"%s\"", new_cluster.bindir, old_cluster.controldata.chkpnt_nxtmxoff, - old_cluster.controldata.chkpnt_nxtmulti, + old_chkpnt_nxtmulti, old_cluster.controldata.chkpnt_oldstMulti, new_cluster.pgdata); check_ok(); -- 2.47.3