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