diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index cbb69f5..7ba4e10 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -2038,8 +2038,6 @@ TrimMultiXact(void) } LWLockRelease(MultiXactMemberControlLock); - - DetermineSafeOldestOffset(MultiXactState->oldestMultiXactId); } /* @@ -2143,13 +2141,11 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid) Assert(MultiXactIdIsValid(oldest_datminmxid)); /* - * Since multixacts wrap differently from transaction IDs, this logic is - * not entirely correct: in some scenarios we could go for longer than 2 - * billion multixacts without seeing any data loss, and in some others we - * could get in trouble before that if the new pg_multixact/members data - * stomps on the previous cycle's data. For lack of a better mechanism we - * use the same logic as for transaction IDs, that is, start taking action - * halfway around the oldest potentially-existing multixact. + * We pretend that a wrap will happen halfway through the multixact ID + * space, but that's not really true, because multixacts wrap differently + * from transaction IDs. Note that, separately from any concern about + * multixact IDs wrapping, we must ensure that multixact members do not + * wrap. Limits for that are set in DetermineSafeOldestOffset, not here. */ multiWrapLimit = oldest_datminmxid + (MaxMultiXactId >> 1); if (multiWrapLimit < FirstMultiXactId) @@ -2204,8 +2200,6 @@ SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid) curMulti = MultiXactState->nextMXact; LWLockRelease(MultiXactGenLock); - DetermineSafeOldestOffset(oldest_datminmxid); - /* Log the info */ ereport(DEBUG1, (errmsg("MultiXactId wrap limit is %u, limited by database with OID %u", @@ -2300,8 +2294,6 @@ MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB) { if (MultiXactIdPrecedes(MultiXactState->oldestMultiXactId, oldestMulti)) SetMultiXactIdLimit(oldestMulti, oldestMultiDB); - else - DetermineSafeOldestOffset(oldestMulti); } /* @@ -2479,14 +2471,6 @@ DetermineSafeOldestOffset(MultiXactId oldestMXact) MultiXactOffset oldestOffset; /* - * Can't do this while initdb'ing or in the startup process while - * replaying WAL: the segment file to read might have not yet been - * created, or already been removed. - */ - if (IsBootstrapProcessingMode() || InRecovery) - return; - - /* * We determine the safe upper bound for offsets of new xacts by reading * the offset of the oldest multixact, and going back one segment. This * way, the sequence of multixact member segments will always have a @@ -2734,6 +2718,13 @@ TruncateMultiXact(void) SimpleLruTruncate(MultiXactOffsetCtl, MultiXactIdToOffsetPage(oldestMXact)); + + /* + * Now, and only now, we can advance the stop point for multixact members. + * If we did it any sooner, the segments we deleted above might already + * have been overwritten with new members. That would be bad. + */ + DetermineSafeOldestOffset(oldestMXact); } /*