Consolidate VACUUM xid cutoff logic.
authorPeter Geoghegan <pg@bowt.ie>
Sat, 12 Feb 2022 02:26:15 +0000 (18:26 -0800)
committerPeter Geoghegan <pg@bowt.ie>
Sat, 12 Feb 2022 02:26:15 +0000 (18:26 -0800)
Push the logic for determining whether or not a VACUUM operation will be
aggressive down into vacuum_set_xid_limits().  This makes the function's
signature significantly simpler, and seems clearer overall.

Author: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/CAH2-WzkymFbz6D_vL+jmqSn_5q1wsFvFrE+37yLgL_Rkfd6Gzg@mail.gmail.com

src/backend/access/heap/vacuumlazy.c
src/backend/commands/cluster.c
src/backend/commands/vacuum.c
src/include/commands/vacuum.h

index fed25f492944a2320476613c5ef34d6775935f3e..d57055674edbae997941b9ec9e18676d2619151c 100644 (file)
@@ -323,8 +323,6 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
                                minmulti_updated;
        BlockNumber orig_rel_pages;
        char      **indnames = NULL;
-       TransactionId xidFullScanLimit;
-       MultiXactId mxactFullScanLimit;
        BlockNumber new_rel_pages;
        BlockNumber new_rel_allvisible;
        double          new_live_tuples;
@@ -352,24 +350,24 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
        pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM,
                                                                  RelationGetRelid(rel));
 
-       vacuum_set_xid_limits(rel,
-                                                 params->freeze_min_age,
-                                                 params->freeze_table_age,
-                                                 params->multixact_freeze_min_age,
-                                                 params->multixact_freeze_table_age,
-                                                 &OldestXmin, &FreezeLimit, &xidFullScanLimit,
-                                                 &MultiXactCutoff, &mxactFullScanLimit);
-
        /*
-        * We request an aggressive scan if the table's frozen Xid is now older
-        * than or equal to the requested Xid full-table scan limit; or if the
-        * table's minimum MultiXactId is older than or equal to the requested
-        * mxid full-table scan limit; or if DISABLE_PAGE_SKIPPING was specified.
+        * Get OldestXmin cutoff, which is used to determine which deleted tuples
+        * are considered DEAD, not just RECENTLY_DEAD.  Also get related cutoffs
+        * used to determine which XIDs/MultiXactIds will be frozen.
+        *
+        * If this is an aggressive VACUUM, then we're strictly required to freeze
+        * any and all XIDs from before FreezeLimit, so that we will be able to
+        * safely advance relfrozenxid up to FreezeLimit below (we must be able to
+        * advance relminmxid up to MultiXactCutoff, too).
         */
-       aggressive = TransactionIdPrecedesOrEquals(rel->rd_rel->relfrozenxid,
-                                                                                          xidFullScanLimit);
-       aggressive |= MultiXactIdPrecedesOrEquals(rel->rd_rel->relminmxid,
-                                                                                         mxactFullScanLimit);
+       aggressive = vacuum_set_xid_limits(rel,
+                                                                          params->freeze_min_age,
+                                                                          params->freeze_table_age,
+                                                                          params->multixact_freeze_min_age,
+                                                                          params->multixact_freeze_table_age,
+                                                                          &OldestXmin, &FreezeLimit,
+                                                                          &MultiXactCutoff);
+
        skipwithvm = true;
        if (params->options & VACOPT_DISABLE_PAGE_SKIPPING)
        {
index 2e8efe4f8fc151c5fa9b97b35eb07898e5610915..02a7e94bf9b1c9d76136b76ed447145343452c29 100644 (file)
@@ -857,8 +857,7 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
         * not to be aggressive about this.
         */
        vacuum_set_xid_limits(OldHeap, 0, 0, 0, 0,
-                                                 &OldestXmin, &FreezeXid, NULL, &MultiXactCutoff,
-                                                 NULL);
+                                                 &OldestXmin, &FreezeXid, &MultiXactCutoff);
 
        /*
         * FreezeXid will become the table's new relfrozenxid, and that mustn't go
index 37413dd43e951851d7f0645e9dfebf333537f5c8..b6767a5ff8cd53176b22e13ef2c8d4d5de04320c 100644 (file)
@@ -943,24 +943,18 @@ get_all_vacuum_rels(int options)
  * Input parameters are the target relation, applicable freeze age settings.
  *
  * The output parameters are:
- * - oldestXmin is the cutoff value used to distinguish whether tuples are
- *      DEAD or RECENTLY_DEAD (see HeapTupleSatisfiesVacuum).
+ * - oldestXmin is the Xid below which tuples deleted by any xact (that
+ *   committed) should be considered DEAD, not just RECENTLY_DEAD.
  * - freezeLimit is the Xid below which all Xids are replaced by
  *      FrozenTransactionId during vacuum.
- * - xidFullScanLimit (computed from freeze_table_age parameter)
- *      represents a minimum Xid value; a table whose relfrozenxid is older than
- *      this will have a full-table vacuum applied to it, to freeze tuples across
- *      the whole table.  Vacuuming a table younger than this value can use a
- *      partial scan.
- * - multiXactCutoff is the value below which all MultiXactIds are removed from
- *      Xmax.
- * - mxactFullScanLimit is a value against which a table's relminmxid value is
- *      compared to produce a full-table vacuum, as with xidFullScanLimit.
+ * - multiXactCutoff is the value below which all MultiXactIds are removed
+ *   from Xmax.
  *
- * xidFullScanLimit and mxactFullScanLimit can be passed as NULL if caller is
- * not interested.
+ * Return value indicates if vacuumlazy.c caller should make its VACUUM
+ * operation aggressive.  An aggressive VACUUM must advance relfrozenxid up to
+ * FreezeLimit, and relminmxid up to multiXactCutoff.
  */
-void
+bool
 vacuum_set_xid_limits(Relation rel,
                                          int freeze_min_age,
                                          int freeze_table_age,
@@ -968,9 +962,7 @@ vacuum_set_xid_limits(Relation rel,
                                          int multixact_freeze_table_age,
                                          TransactionId *oldestXmin,
                                          TransactionId *freezeLimit,
-                                         TransactionId *xidFullScanLimit,
-                                         MultiXactId *multiXactCutoff,
-                                         MultiXactId *mxactFullScanLimit)
+                                         MultiXactId *multiXactCutoff)
 {
        int                     freezemin;
        int                     mxid_freezemin;
@@ -980,6 +972,7 @@ vacuum_set_xid_limits(Relation rel,
        MultiXactId oldestMxact;
        MultiXactId mxactLimit;
        MultiXactId safeMxactLimit;
+       int                     freezetable;
 
        /*
         * We can always ignore processes running lazy vacuum.  This is because we
@@ -1097,64 +1090,60 @@ vacuum_set_xid_limits(Relation rel,
 
        *multiXactCutoff = mxactLimit;
 
-       if (xidFullScanLimit != NULL)
-       {
-               int                     freezetable;
-
-               Assert(mxactFullScanLimit != NULL);
-
-               /*
-                * Determine the table freeze age to use: as specified by the caller,
-                * or vacuum_freeze_table_age, but in any case not more than
-                * autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
-                * VACUUM schedule, the nightly VACUUM gets a chance to freeze tuples
-                * before anti-wraparound autovacuum is launched.
-                */
-               freezetable = freeze_table_age;
-               if (freezetable < 0)
-                       freezetable = vacuum_freeze_table_age;
-               freezetable = Min(freezetable, autovacuum_freeze_max_age * 0.95);
-               Assert(freezetable >= 0);
-
-               /*
-                * Compute XID limit causing a full-table vacuum, being careful not to
-                * generate a "permanent" XID.
-                */
-               limit = ReadNextTransactionId() - freezetable;
-               if (!TransactionIdIsNormal(limit))
-                       limit = FirstNormalTransactionId;
+       /*
+        * Done setting output parameters; just need to figure out if caller needs
+        * to do an aggressive VACUUM or not.
+        *
+        * Determine the table freeze age to use: as specified by the caller, or
+        * vacuum_freeze_table_age, but in any case not more than
+        * autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
+        * VACUUM schedule, the nightly VACUUM gets a chance to freeze tuples
+        * before anti-wraparound autovacuum is launched.
+        */
+       freezetable = freeze_table_age;
+       if (freezetable < 0)
+               freezetable = vacuum_freeze_table_age;
+       freezetable = Min(freezetable, autovacuum_freeze_max_age * 0.95);
+       Assert(freezetable >= 0);
 
-               *xidFullScanLimit = limit;
+       /*
+        * Compute XID limit causing an aggressive vacuum, being careful not to
+        * generate a "permanent" XID
+        */
+       limit = ReadNextTransactionId() - freezetable;
+       if (!TransactionIdIsNormal(limit))
+               limit = FirstNormalTransactionId;
+       if (TransactionIdPrecedesOrEquals(rel->rd_rel->relfrozenxid,
+                                                                         limit))
+               return true;
 
-               /*
-                * Similar to the above, determine the table freeze age to use for
-                * multixacts: as specified by the caller, or
-                * vacuum_multixact_freeze_table_age, but in any case not more than
-                * autovacuum_multixact_freeze_table_age * 0.95, so that if you have
-                * e.g. nightly VACUUM schedule, the nightly VACUUM gets a chance to
-                * freeze multixacts before anti-wraparound autovacuum is launched.
-                */
-               freezetable = multixact_freeze_table_age;
-               if (freezetable < 0)
-                       freezetable = vacuum_multixact_freeze_table_age;
-               freezetable = Min(freezetable,
-                                                 effective_multixact_freeze_max_age * 0.95);
-               Assert(freezetable >= 0);
+       /*
+        * Similar to the above, determine the table freeze age to use for
+        * multixacts: as specified by the caller, or
+        * vacuum_multixact_freeze_table_age, but in any case not more than
+        * autovacuum_multixact_freeze_table_age * 0.95, so that if you have e.g.
+        * nightly VACUUM schedule, the nightly VACUUM gets a chance to freeze
+        * multixacts before anti-wraparound autovacuum is launched.
+        */
+       freezetable = multixact_freeze_table_age;
+       if (freezetable < 0)
+               freezetable = vacuum_multixact_freeze_table_age;
+       freezetable = Min(freezetable,
+                                         effective_multixact_freeze_max_age * 0.95);
+       Assert(freezetable >= 0);
 
-               /*
-                * Compute MultiXact limit causing a full-table vacuum, being careful
-                * to generate a valid MultiXact value.
-                */
-               mxactLimit = ReadNextMultiXactId() - freezetable;
-               if (mxactLimit < FirstMultiXactId)
-                       mxactLimit = FirstMultiXactId;
+       /*
+        * Compute MultiXact limit causing an aggressive vacuum, being careful to
+        * generate a valid MultiXact value
+        */
+       mxactLimit = ReadNextMultiXactId() - freezetable;
+       if (mxactLimit < FirstMultiXactId)
+               mxactLimit = FirstMultiXactId;
+       if (MultiXactIdPrecedesOrEquals(rel->rd_rel->relminmxid,
+                                                                       mxactLimit))
+               return true;
 
-               *mxactFullScanLimit = mxactLimit;
-       }
-       else
-       {
-               Assert(mxactFullScanLimit == NULL);
-       }
+       return false;
 }
 
 /*
index e5e548d6b9a63d78677a2fbbef57a6c9ffb07556..d64f6268f232d34f208adca94ca5772b6016c4c5 100644 (file)
@@ -286,15 +286,13 @@ extern void vac_update_relstats(Relation relation,
                                                                bool *frozenxid_updated,
                                                                bool *minmulti_updated,
                                                                bool in_outer_xact);
-extern void vacuum_set_xid_limits(Relation rel,
+extern bool vacuum_set_xid_limits(Relation rel,
                                                                  int freeze_min_age, int freeze_table_age,
                                                                  int multixact_freeze_min_age,
                                                                  int multixact_freeze_table_age,
                                                                  TransactionId *oldestXmin,
                                                                  TransactionId *freezeLimit,
-                                                                 TransactionId *xidFullScanLimit,
-                                                                 MultiXactId *multiXactCutoff,
-                                                                 MultiXactId *mxactFullScanLimit);
+                                                                 MultiXactId *multiXactCutoff);
 extern bool vacuum_xid_failsafe_check(TransactionId relfrozenxid,
                                                                          MultiXactId relminmxid);
 extern void vac_update_datfrozenxid(void);