Revert "Add eager and lazy freezing strategies to VACUUM."
authorPeter Geoghegan <[email protected]>
Thu, 26 Jan 2023 06:22:27 +0000 (22:22 -0800)
committerPeter Geoghegan <[email protected]>
Thu, 26 Jan 2023 06:22:27 +0000 (22:22 -0800)
This reverts commit 4d417992613949af35530b4e8e83670c4e67e1b2.  Broad
concerns about regressions caused by eager freezing strategy have been
raised.  Whether or not these concerns can be worked through in any time
frame is far from certain.

Discussion: https://postgr.es/m/20230126004347[email protected]

12 files changed:
doc/src/sgml/config.sgml
doc/src/sgml/maintenance.sgml
doc/src/sgml/ref/create_table.sgml
src/backend/access/common/reloptions.c
src/backend/access/heap/heapam.c
src/backend/access/heap/vacuumlazy.c
src/backend/commands/vacuum.c
src/backend/postmaster/autovacuum.c
src/backend/utils/misc/guc_tables.c
src/backend/utils/misc/postgresql.conf.sample
src/include/commands/vacuum.h
src/include/utils/rel.h

index 9be0438c68ff27d56945b174c0bb4cc1260f5a6b..f985afc009d04677618c27c8d57e88b60ecc0659 100644 (file)
@@ -9272,36 +9272,6 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
       </listitem>
      </varlistentry>
 
-     <varlistentry id="guc-vacuum-freeze-strategy-threshold" xreflabel="vacuum_freeze_strategy_threshold">
-      <term><varname>vacuum_freeze_strategy_threshold</varname> (<type>integer</type>)
-      <indexterm>
-       <primary><varname>vacuum_freeze_strategy_threshold</varname> configuration parameter</primary>
-      </indexterm>
-      </term>
-      <listitem>
-       <para>
-        Specifies the cutoff storage size that
-        <command>VACUUM</command> should use to determine its freezing
-        strategy.  This is applied by comparing it to the size of the
-        target table's <glossterm linkend="glossary-fork">main
-         fork</glossterm> at the beginning of each <command>VACUUM</command>.
-        Eager freezing strategy is used by <command>VACUUM</command>
-        when the table's main fork size exceeds this value.
-        <command>VACUUM</command> <emphasis>always</emphasis> uses
-        eager freezing strategy when processing <glossterm
-         linkend="glossary-unlogged">unlogged</glossterm> tables,
-        regardless of this setting.  Otherwise <command>VACUUM</command>
-        uses lazy freezing strategy.  For more information see <xref
-         linkend="vacuum-for-wraparound"/>.
-       </para>
-       <para>
-        If this value is specified without units, it is taken as
-        megabytes.  The default is four gigabytes
-        (<literal>4GB</literal>).
-       </para>
-      </listitem>
-     </varlistentry>
-
      <varlistentry id="guc-vacuum-failsafe-age" xreflabel="vacuum_failsafe_age">
       <term><varname>vacuum_failsafe_age</varname> (<type>integer</type>)
       <indexterm>
index bc21de300671d26a1d6d33958f93d9a59a1ae7d9..9cf9d030a8a04074af9fc0f9097b108a0b21d9bc 100644 (file)
    </note>
 
    <para>
-    <xref linkend="guc-vacuum-freeze-strategy-threshold"/> controls
-    <command>VACUUM</command>'s freezing strategy.  The
-    <firstterm>eager freezing strategy</firstterm> makes
-    <command>VACUUM</command> freeze all rows on a page whenever each
-    and every row on the page is considered visible to all current
-    transactions (immediately after dead row versions are removed).
-    Freezing pages early and in batch often spreads out the overhead
-    of freezing over time.  <command>VACUUM</command> consistently
-    avoids allowing unfrozen all-visible pages to build up, improving
-    system level performance stability.  The <firstterm>lazy freezing
-     strategy</firstterm> makes <command>VACUUM</command> determine
-    whether pages should be frozen on the basis of the age of the
-    oldest XID on the page.  Freezing pages lazily sometimes avoids
-    the overhead of freezing that turns out to have been unnecessary
-    because the rows were modified soon after freezing took place.
-   </para>
-
-   <para>
-    <xref linkend="guc-vacuum-freeze-min-age"/> controls how old an
-    XID value has to be before pages with rows bearing that XID are
-    frozen.  This setting is an additional trigger criteria for
-    freezing a page's tuples.  It is used by both freezing strategies,
-    though it typically has little impact when <command>VACUUM</command>
-    uses the eager freezing strategy.
+    <xref linkend="guc-vacuum-freeze-min-age"/>
+    controls how old an XID value has to be before rows bearing that XID will be
+    frozen.  Increasing this setting may avoid unnecessary work if the
+    rows that would otherwise be frozen will soon be modified again,
+    but decreasing this setting increases
+    the number of transactions that can elapse before the table must be
+    vacuumed again.
    </para>
 
    <para>
     always use its aggressive strategy.
    </para>
 
-   <para>
-    Controlling the overhead of freezing existing all-visible pages
-    during aggressive vacuuming is the goal of the eager freezing
-    strategy.  Increasing <varname>vacuum_freeze_strategy_threshold</varname>
-    may avoid unnecessary work, but it increases the risk of an
-    eventual aggressive vacuum that performs an excessive amount of
-    <quote>catch up</quote> freezing all at once.
-   </para>
-
    <para>
     The maximum time that a table can go unvacuumed is two billion
     transactions minus the <varname>vacuum_freeze_min_age</varname> value at
     the time of the last aggressive vacuum. If it were to go
-    unvacuumed for longer than that, the system could temporarily refuse to
-    allocate new transaction IDs.  To ensure that this never happens,
+    unvacuumed for longer than
+    that, data loss could result.  To ensure that this does not happen,
     autovacuum is invoked on any table that might contain unfrozen rows with
     XIDs older than the age specified by the configuration parameter <xref
     linkend="guc-autovacuum-freeze-max-age"/>.  (This will happen even if
    </para>
 
    <para>
-    One disadvantage of increasing <varname>autovacuum_freeze_max_age</varname>
+    The sole disadvantage of increasing <varname>autovacuum_freeze_max_age</varname>
     (and <varname>vacuum_freeze_table_age</varname> along with it) is that
     the <filename>pg_xact</filename> and <filename>pg_commit_ts</filename>
     subdirectories of the database cluster will take more space, because it
@@ -864,8 +838,8 @@ vacuum insert threshold = vacuum base insert threshold + vacuum insert scale fac
     For tables which receive <command>INSERT</command> operations but no or
     almost no <command>UPDATE</command>/<command>DELETE</command> operations,
     it may be beneficial to lower the table's
-    <xref linkend="reloption-autovacuum-freeze-strategy-threshold"/>
-    to allow freezing to take place proactively.  The number of obsolete tuples and
+    <xref linkend="reloption-autovacuum-freeze-min-age"/> as this may allow
+    tuples to be frozen by earlier vacuums.  The number of obsolete tuples and
     the number of inserted tuples are obtained from the cumulative statistics system;
     it is a semi-accurate count updated by each <command>UPDATE</command>,
     <command>DELETE</command> and <command>INSERT</command> operation.  (It is
index 3b40b5355d8a660b60c06844e5b9f1513c280edd..a03dee4afef538fd3c5cb3f68550c5ca25ceb290 100644 (file)
@@ -1781,20 +1781,6 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
     </listitem>
    </varlistentry>
 
-   <varlistentry id="reloption-autovacuum-freeze-strategy-threshold" xreflabel="autovacuum_freeze_strategy_threshold">
-    <term><literal>autovacuum_freeze_strategy_threshold</literal>, <literal>toast.autovacuum_freeze_strategy_threshold</literal> (<type>integer</type>)
-    <indexterm>
-     <primary><varname>autovacuum_freeze_strategy_threshold</varname> storage parameter</primary>
-    </indexterm>
-    </term>
-    <listitem>
-     <para>
-      Per-table value for <xref linkend="guc-vacuum-freeze-strategy-threshold"/>
-      parameter.
-     </para>
-    </listitem>
-   </varlistentry>
-
    <varlistentry id="reloption-log-autovacuum-min-duration" xreflabel="log_autovacuum_min_duration">
     <term><literal>log_autovacuum_min_duration</literal>, <literal>toast.log_autovacuum_min_duration</literal> (<type>integer</type>)
     <indexterm>
index dfa802416fc9c47715b2276d3ed77a723a78e853..14c23101adf4bbd74d3bf7bf556b046f7b5770cd 100644 (file)
@@ -312,14 +312,6 @@ static relopt_int intRelOpts[] =
            ShareUpdateExclusiveLock
        }, -1, 0, 2000000000
    },
-   {
-       {
-           "autovacuum_freeze_strategy_threshold",
-           "Table size at which VACUUM freezes using eager strategy, in megabytes.",
-           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
-           ShareUpdateExclusiveLock
-       }, -1, 0, MAX_KILOBYTES
-   },
    {
        {
            "log_autovacuum_min_duration",
@@ -1871,8 +1863,6 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_max_age)},
        {"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,
        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_table_age)},
-       {"autovacuum_freeze_strategy_threshold", RELOPT_TYPE_INT,
-       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_strategy_threshold)},
        {"log_autovacuum_min_duration", RELOPT_TYPE_INT,
        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)},
        {"toast_tuple_target", RELOPT_TYPE_INT,
index fec041d6cdd186e2588907cde3c29394d62d5685..e6024a980bbacab232ccbe3cdfc1de5ebde5b79f 100644 (file)
@@ -7057,7 +7057,6 @@ heap_freeze_tuple(HeapTupleHeader tuple,
    cutoffs.OldestMxact = MultiXactCutoff;
    cutoffs.FreezeLimit = FreezeLimit;
    cutoffs.MultiXactCutoff = MultiXactCutoff;
-   cutoffs.freeze_strategy_threshold_pages = 0;
 
    pagefrz.freeze_required = true;
    pagefrz.FreezePageRelfrozenXid = FreezeLimit;
index e3f86493b90805239d5ab363e3bcaaaa647f4f87..8f14cf85f38bc7babc50057af7fd33eea9a8386e 100644 (file)
@@ -153,8 +153,6 @@ typedef struct LVRelState
    bool        aggressive;
    /* Use visibility map to skip? (disabled by DISABLE_PAGE_SKIPPING) */
    bool        skipwithvm;
-   /* Eagerly freeze pages that are eligible to become all-frozen? */
-   bool        eager_freeze_strategy;
    /* Wraparound failsafe has been triggered? */
    bool        failsafe_active;
    /* Consider index vacuuming bypass optimization? */
@@ -245,7 +243,6 @@ typedef struct LVSavedErrInfo
 
 /* non-export function s */
 static void lazy_scan_heap(LVRelState *vacrel);
-static void lazy_scan_strategy(LVRelState *vacrel);
 static BlockNumber lazy_scan_skip(LVRelState *vacrel, Buffer *vmbuffer,
                                  BlockNumber next_block,
                                  bool *next_unskippable_allvis,
@@ -475,10 +472,6 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
 
    vacrel->skipwithvm = skipwithvm;
 
-   /*
-    * Now determine VACUUM's freezing strategy
-    */
-   lazy_scan_strategy(vacrel);
    if (verbose)
    {
        if (vacrel->aggressive)
@@ -1274,38 +1267,6 @@ lazy_scan_heap(LVRelState *vacrel)
        lazy_cleanup_all_indexes(vacrel);
 }
 
-/*
- * lazy_scan_strategy() -- Determine freezing strategy.
- *
- * Our lazy freezing strategy is useful when putting off the work of freezing
- * totally avoids freezing that turns out to have been wasted effort later on.
- * Our eager freezing strategy is useful with larger tables that experience
- * continual growth, where freezing pages proactively is needed just to avoid
- * falling behind on freezing (eagerness is also likely to be cheaper in the
- * short/medium term for such tables, but the long term picture matters most).
- */
-static void
-lazy_scan_strategy(LVRelState *vacrel)
-{
-   BlockNumber rel_pages = vacrel->rel_pages;
-
-   /*
-    * Decide freezing strategy.
-    *
-    * The eager freezing strategy is used whenever rel_pages exceeds a
-    * threshold controlled by the freeze_strategy_threshold GUC/reloption.
-    *
-    * Also freeze eagerly with an unlogged or temp table, where the total
-    * cost of freezing pages is mostly just the cycles needed to prepare a
-    * set of freeze plans.  Executing the freeze plans adds very little cost.
-    * Dirtying extra pages isn't a concern, either; VACUUM will definitely
-    * set PD_ALL_VISIBLE on affected pages, regardless of freezing strategy.
-    */
-   vacrel->eager_freeze_strategy =
-       (rel_pages > vacrel->cutoffs.freeze_strategy_threshold_pages ||
-        !RelationIsPermanent(vacrel->rel));
-}
-
 /*
  * lazy_scan_skip() -- set up range of skippable blocks using visibility map.
  *
@@ -1834,12 +1795,10 @@ retry:
     * one XID/MXID from before FreezeLimit/MultiXactCutoff is present.  Also
     * freeze when pruning generated an FPI, if doing so means that we set the
     * page all-frozen afterwards (might not happen until final heap pass).
-    * When ongoing VACUUM opted to use the eager freezing strategy we freeze
-    * any page that will thereby become all-frozen in the visibility map.
     */
    if (pagefrz.freeze_required || tuples_frozen == 0 ||
        (prunestate->all_visible && prunestate->all_frozen &&
-        (fpi_before != pgWalUsage.wal_fpi || vacrel->eager_freeze_strategy)))
+        fpi_before != pgWalUsage.wal_fpi))
    {
        /*
         * We're freezing the page.  Our final NewRelfrozenXid doesn't need to
index 033a9db90cefdc03f30766ca171a1e11bce59e02..7b1a4b127eb397f51f46b5e5f80557044875fac2 100644 (file)
@@ -68,7 +68,6 @@ int           vacuum_freeze_min_age;
 int            vacuum_freeze_table_age;
 int            vacuum_multixact_freeze_min_age;
 int            vacuum_multixact_freeze_table_age;
-int            vacuum_freeze_strategy_threshold;
 int            vacuum_failsafe_age;
 int            vacuum_multixact_failsafe_age;
 
@@ -265,7 +264,6 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
        params.freeze_table_age = 0;
        params.multixact_freeze_min_age = 0;
        params.multixact_freeze_table_age = 0;
-       params.freeze_strategy_threshold = 0;
    }
    else
    {
@@ -273,7 +271,6 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
        params.freeze_table_age = -1;
        params.multixact_freeze_min_age = -1;
        params.multixact_freeze_table_age = -1;
-       params.freeze_strategy_threshold = -1;
    }
 
    /* user-invoked vacuum is never "for wraparound" */
@@ -965,9 +962,7 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
                multixact_freeze_min_age,
                freeze_table_age,
                multixact_freeze_table_age,
-               effective_multixact_freeze_max_age,
-               freeze_strategy_threshold;
-   uint64      threshold_strategy_pages;
+               effective_multixact_freeze_max_age;
    TransactionId nextXID,
                safeOldestXmin,
                aggressiveXIDCutoff;
@@ -980,7 +975,6 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
    multixact_freeze_min_age = params->multixact_freeze_min_age;
    freeze_table_age = params->freeze_table_age;
    multixact_freeze_table_age = params->multixact_freeze_table_age;
-   freeze_strategy_threshold = params->freeze_strategy_threshold;
 
    /* Set pg_class fields in cutoffs */
    cutoffs->relfrozenxid = rel->rd_rel->relfrozenxid;
@@ -1095,23 +1089,6 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
    if (MultiXactIdPrecedes(cutoffs->OldestMxact, cutoffs->MultiXactCutoff))
        cutoffs->MultiXactCutoff = cutoffs->OldestMxact;
 
-   /*
-    * Determine the freeze_strategy_threshold to use: as specified by the
-    * caller, or vacuum_freeze_strategy_threshold
-    */
-   if (freeze_strategy_threshold < 0)
-       freeze_strategy_threshold = vacuum_freeze_strategy_threshold;
-   Assert(freeze_strategy_threshold >= 0);
-
-   /*
-    * Convert MB-based freeze_strategy_threshold to page-based value used by
-    * our vacuumlazy.c caller, while being careful to avoid overflow
-    */
-   threshold_strategy_pages =
-       ((uint64) freeze_strategy_threshold * 1024 * 1024) / BLCKSZ;
-   threshold_strategy_pages = Min(threshold_strategy_pages, MaxBlockNumber);
-   cutoffs->freeze_strategy_threshold_pages = threshold_strategy_pages;
-
    /*
     * Finally, figure out if caller needs to do an aggressive VACUUM or not.
     *
index ecddde3a1eac26d1fb25550b963cf4f3546d51bc..f5ea381c53e92702805dfa5bb111a6fe487eaf79 100644 (file)
@@ -151,7 +151,6 @@ static int  default_freeze_min_age;
 static int default_freeze_table_age;
 static int default_multixact_freeze_min_age;
 static int default_multixact_freeze_table_age;
-static int default_freeze_strategy_threshold;
 
 /* Memory context for long-lived data */
 static MemoryContext AutovacMemCxt;
@@ -2011,7 +2010,6 @@ do_autovacuum(void)
        default_freeze_table_age = 0;
        default_multixact_freeze_min_age = 0;
        default_multixact_freeze_table_age = 0;
-       default_freeze_strategy_threshold = 0;
    }
    else
    {
@@ -2019,7 +2017,6 @@ do_autovacuum(void)
        default_freeze_table_age = vacuum_freeze_table_age;
        default_multixact_freeze_min_age = vacuum_multixact_freeze_min_age;
        default_multixact_freeze_table_age = vacuum_multixact_freeze_table_age;
-       default_freeze_strategy_threshold = vacuum_freeze_strategy_threshold;
    }
 
    ReleaseSysCache(tuple);
@@ -2804,7 +2801,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
        int         freeze_table_age;
        int         multixact_freeze_min_age;
        int         multixact_freeze_table_age;
-       int         freeze_strategy_threshold;
        int         vac_cost_limit;
        double      vac_cost_delay;
        int         log_min_duration;
@@ -2854,11 +2850,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
            ? avopts->multixact_freeze_table_age
            : default_multixact_freeze_table_age;
 
-       freeze_strategy_threshold = (avopts &&
-                                    avopts->freeze_strategy_threshold >= 0)
-           ? avopts->freeze_strategy_threshold
-           : default_freeze_strategy_threshold;
-
        tab = palloc(sizeof(autovac_table));
        tab->at_relid = relid;
        tab->at_sharedrel = classForm->relisshared;
@@ -2886,7 +2877,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
        tab->at_params.freeze_table_age = freeze_table_age;
        tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age;
        tab->at_params.multixact_freeze_table_age = multixact_freeze_table_age;
-       tab->at_params.freeze_strategy_threshold = freeze_strategy_threshold;
        tab->at_params.is_wraparound = wraparound;
        tab->at_params.log_min_duration = log_min_duration;
        tab->at_vacuum_cost_limit = vac_cost_limit;
index dcfa0c4c4b39eed3d1f9bddd3a5d6735da87bd6b..4ac808ed224867ccc5da59318a78947c70f45643 100644 (file)
@@ -2535,20 +2535,6 @@ struct config_int ConfigureNamesInt[] =
        NULL, NULL, NULL
    },
 
-   {
-       {"vacuum_freeze_strategy_threshold", PGC_USERSET, CLIENT_CONN_STATEMENT,
-           gettext_noop("Table size at which VACUUM freezes using eager strategy, in megabytes."),
-           gettext_noop("This is applied by comparing it to the size of a table's main fork at "
-                        "the beginning of each VACUUM. Eager freezing strategy is used when size "
-                        "exceeds the threshold, or when table is a temporary or unlogged table. "
-                        "Otherwise lazy freezing strategy is used."),
-           GUC_UNIT_MB
-       },
-       &vacuum_freeze_strategy_threshold,
-       4096, 0, MAX_KILOBYTES,
-       NULL, NULL, NULL
-   },
-
    {
        {"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_PRIMARY,
            gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
index fda695e75674947839539dab6ad602f384ae6b95..d06074b86f6de8fce9dedffc1207685dcf5900e8 100644 (file)
 #vacuum_multixact_freeze_table_age = 150000000
 #vacuum_multixact_freeze_min_age = 5000000
 #vacuum_multixact_failsafe_age = 1600000000
-#vacuum_freeze_strategy_threshold = 4GB
 #bytea_output = 'hex'          # hex, escape
 #xmlbinary = 'base64'
 #xmloption = 'content'
index 2a4dae7dd873d4596dd3ae0b0f9f7f0138e06c32..689dbb7702435fa74ad45886647699ad0edb6471 100644 (file)
@@ -222,9 +222,6 @@ typedef struct VacuumParams
                                             * use default */
    int         multixact_freeze_table_age; /* multixact age at which to scan
                                             * whole table */
-   int         freeze_strategy_threshold;  /* threshold to use eager
-                                            * freezing, in megabytes, -1 to
-                                            * use default */
    bool        is_wraparound;  /* force a for-wraparound vacuum */
    int         log_min_duration;   /* minimum execution threshold in ms at
                                     * which autovacuum is logged, -1 to use
@@ -277,14 +274,6 @@ struct VacuumCutoffs
     */
    TransactionId FreezeLimit;
    MultiXactId MultiXactCutoff;
-
-   /*
-    * Eager freezing strategy is used whenever target rel's main fork size
-    * exceeds freeze_strategy_threshold_pages.  Otherwise lazy freezing
-    * strategy is used.  (Actually, there are exceptions.  Non-permanent
-    * tables always use eager freezing strategy.)
-    */
-   BlockNumber freeze_strategy_threshold_pages;
 };
 
 /*
@@ -308,7 +297,6 @@ extern PGDLLIMPORT int vacuum_freeze_min_age;
 extern PGDLLIMPORT int vacuum_freeze_table_age;
 extern PGDLLIMPORT int vacuum_multixact_freeze_min_age;
 extern PGDLLIMPORT int vacuum_multixact_freeze_table_age;
-extern PGDLLIMPORT int vacuum_freeze_strategy_threshold;
 extern PGDLLIMPORT int vacuum_failsafe_age;
 extern PGDLLIMPORT int vacuum_multixact_failsafe_age;
 
index 39c7ccf0c89d639fd6b653e458e981645051a19b..af9785038d39bcd9e8c22a0bad3b869b8a85fcb1 100644 (file)
@@ -314,7 +314,6 @@ typedef struct AutoVacOpts
    int         multixact_freeze_min_age;
    int         multixact_freeze_max_age;
    int         multixact_freeze_table_age;
-   int         freeze_strategy_threshold;
    int         log_min_duration;
    float8      vacuum_cost_delay;
    float8      vacuum_scale_factor;