aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/cluster.c11
-rw-r--r--src/backend/commands/vacuum.c39
2 files changed, 29 insertions, 21 deletions
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index cd19e35319e..322d6bb2f18 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -806,9 +806,10 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
Form_pg_class relform;
TupleDesc oldTupDesc PG_USED_FOR_ASSERTS_ONLY;
TupleDesc newTupDesc PG_USED_FOR_ASSERTS_ONLY;
- TransactionId OldestXmin;
- TransactionId FreezeXid;
- MultiXactId MultiXactCutoff;
+ TransactionId OldestXmin,
+ FreezeXid;
+ MultiXactId OldestMxact,
+ MultiXactCutoff;
bool use_sort;
double num_tuples = 0,
tups_vacuumed = 0,
@@ -896,8 +897,8 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
* Since we're going to rewrite the whole table anyway, there's no reason
* not to be aggressive about this.
*/
- vacuum_set_xid_limits(OldHeap, 0, 0, 0, 0,
- &OldestXmin, &FreezeXid, &MultiXactCutoff);
+ vacuum_set_xid_limits(OldHeap, 0, 0, 0, 0, &OldestXmin, &OldestMxact,
+ &FreezeXid, &MultiXactCutoff);
/*
* FreezeXid will become the table's new relfrozenxid, and that mustn't go
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 50a4a612e58..deec4887bec 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -945,14 +945,22 @@ get_all_vacuum_rels(int options)
* The output parameters are:
* - 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.
- * - multiXactCutoff is the value below which all MultiXactIds are removed
- * from Xmax.
+ * - oldestMxact is the Mxid below which MultiXacts are definitely not
+ * seen as visible by any running transaction.
+ * - freezeLimit is the Xid below which all Xids are definitely replaced by
+ * FrozenTransactionId during aggressive vacuums.
+ * - multiXactCutoff is the value below which all MultiXactIds are definitely
+ * removed from Xmax during aggressive vacuums.
*
* 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.
+ * FreezeLimit (at a minimum), and relminmxid up to multiXactCutoff (at a
+ * minimum).
+ *
+ * oldestXmin and oldestMxact are the most recent values that can ever be
+ * passed to vac_update_relstats() as frozenxid and minmulti arguments by our
+ * vacuumlazy.c caller later on. These values should be passed when it turns
+ * out that VACUUM will leave no unfrozen XIDs/XMIDs behind in the table.
*/
bool
vacuum_set_xid_limits(Relation rel,
@@ -961,6 +969,7 @@ vacuum_set_xid_limits(Relation rel,
int multixact_freeze_min_age,
int multixact_freeze_table_age,
TransactionId *oldestXmin,
+ MultiXactId *oldestMxact,
TransactionId *freezeLimit,
MultiXactId *multiXactCutoff)
{
@@ -969,7 +978,6 @@ vacuum_set_xid_limits(Relation rel,
int effective_multixact_freeze_max_age;
TransactionId limit;
TransactionId safeLimit;
- MultiXactId oldestMxact;
MultiXactId mxactLimit;
MultiXactId safeMxactLimit;
int freezetable;
@@ -1065,9 +1073,11 @@ vacuum_set_xid_limits(Relation rel,
effective_multixact_freeze_max_age / 2);
Assert(mxid_freezemin >= 0);
+ /* Remember for caller */
+ *oldestMxact = GetOldestMultiXactId();
+
/* compute the cutoff multi, being careful to generate a valid value */
- oldestMxact = GetOldestMultiXactId();
- mxactLimit = oldestMxact - mxid_freezemin;
+ mxactLimit = *oldestMxact - mxid_freezemin;
if (mxactLimit < FirstMultiXactId)
mxactLimit = FirstMultiXactId;
@@ -1082,8 +1092,8 @@ vacuum_set_xid_limits(Relation rel,
(errmsg("oldest multixact is far in the past"),
errhint("Close open transactions with multixacts soon to avoid wraparound problems.")));
/* Use the safe limit, unless an older mxact is still running */
- if (MultiXactIdPrecedes(oldestMxact, safeMxactLimit))
- mxactLimit = oldestMxact;
+ if (MultiXactIdPrecedes(*oldestMxact, safeMxactLimit))
+ mxactLimit = *oldestMxact;
else
mxactLimit = safeMxactLimit;
}
@@ -1390,12 +1400,9 @@ vac_update_relstats(Relation relation,
* Update relfrozenxid, unless caller passed InvalidTransactionId
* indicating it has no new data.
*
- * Ordinarily, we don't let relfrozenxid go backwards: if things are
- * working correctly, the only way the new frozenxid could be older would
- * be if a previous VACUUM was done with a tighter freeze_min_age, in
- * which case we don't want to forget the work it already did. However,
- * if the stored relfrozenxid is "in the future", then it must be corrupt
- * and it seems best to overwrite it with the cutoff we used this time.
+ * Ordinarily, we don't let relfrozenxid go backwards. However, if the
+ * stored relfrozenxid is "in the future" then it seems best to assume
+ * it's corrupt, and overwrite with the oldest remaining XID in the table.
* This should match vac_update_datfrozenxid() concerning what we consider
* to be "in the future".
*/