@@ -265,18 +265,20 @@ typedef struct MultiXactStateData
265
265
*
266
266
* The oldest valid value among all of the OldestMemberMXactId[] and
267
267
* 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.
280
282
*/
281
283
MultiXactId perBackendXactIds [FLEXIBLE_ARRAY_MEMBER ];
282
284
} MultiXactStateData ;
@@ -2497,8 +2499,9 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
2497
2499
* longer have any running member transaction.
2498
2500
*
2499
2501
* 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.
2502
2505
*/
2503
2506
MultiXactId
2504
2507
GetOldestMultiXactId (void )
@@ -2799,9 +2802,8 @@ ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
2799
2802
* this will also be sufficient to keep us from using too many offsets.
2800
2803
* However, if the average multixact has many members, we might exhaust the
2801
2804
* 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.
2805
2807
*
2806
2808
* To prevent that, if more than a threshold portion of the members space is
2807
2809
* used, we effectively reduce autovacuum_multixact_freeze_max_age and
0 commit comments