@@ -265,18 +265,20 @@ typedef struct MultiXactStateData
265265 *
266266 * The oldest valid value among all of the OldestMemberMXactId[] and
267267 * OldestVisibleMXactId[] entries is considered by vacuum as the earliest
268- * possible value still having any live member transaction. Subtracting
269- * vacuum_multixact_freeze_min_age from that value we obtain the freezing
270- * point for multixacts for that table. Any value older than that is
271- * removed from tuple headers (or "frozen"; see FreezeMultiXactId. Note
272- * that multis that have member xids that are older than the cutoff point
273- * for xids must also be frozen, even if the multis themselves are newer
274- * than the multixid cutoff point). Whenever a full table vacuum happens,
275- * the freezing point so computed is used as the new pg_class.relminmxid
276- * value. The minimum of all those values in a database is stored as
277- * pg_database.datminmxid. In turn, the minimum of all of those values is
278- * stored in pg_control and used as truncation point for pg_multixact. At
279- * checkpoint or restartpoint, unneeded segments are removed.
268+ * possible value still having any live member transaction -- OldestMxact.
269+ * Any value older than that is typically removed from tuple headers, or
270+ * "frozen" via being replaced with a new xmax. VACUUM can sometimes even
271+ * remove an individual MultiXact xmax whose value is >= its OldestMxact
272+ * cutoff, though typically only when no individual member XID is still
273+ * running. See FreezeMultiXactId for full details.
274+ *
275+ * Whenever VACUUM advances relminmxid, then either its OldestMxact cutoff
276+ * or the oldest extant Multi remaining in the table is used as the new
277+ * pg_class.relminmxid value (whichever is earlier). The minimum of all
278+ * relminmxid values in each database is stored in pg_database.datminmxid.
279+ * In turn, the minimum of all of those values is stored in pg_control.
280+ * This is used as the truncation point for pg_multixact when unneeded
281+ * segments get removed by vac_truncate_clog() during vacuuming.
280282 */
281283 MultiXactId perBackendXactIds [FLEXIBLE_ARRAY_MEMBER ];
282284} MultiXactStateData ;
@@ -2497,8 +2499,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
24972499 * longer have any running member transaction.
24982500 *
24992501 * It's not safe to truncate MultiXact SLRU segments on the value returned by
2500- * this function; however, it can be used by a full-table vacuum to set the
2501- * point at which it will be possible to truncate SLRU for that table.
2502+ * this function; however, it can be set as the new relminmxid for any table
2503+ * that VACUUM knows has no remaining MXIDs < the same value. It is only safe
2504+ * to truncate SLRUs when no table can possibly still have a referencing MXID.
25022505 */
25032506MultiXactId
25042507GetOldestMultiXactId (void )
@@ -2799,9 +2802,8 @@ ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
27992802 * this will also be sufficient to keep us from using too many offsets.
28002803 * However, if the average multixact has many members, we might exhaust the
28012804 * members space while still using few enough members that these limits fail
2802- * to trigger full table scans for relminmxid advancement. At that point,
2803- * we'd have no choice but to start failing multixact-creating operations
2804- * with an error.
2805+ * to trigger relminmxid advancement by VACUUM. At that point, we'd have no
2806+ * choice but to start failing multixact-creating operations with an error.
28052807 *
28062808 * To prevent that, if more than a threshold portion of the members space is
28072809 * used, we effectively reduce autovacuum_multixact_freeze_max_age and
0 commit comments