Avoid repeating loads of frozen ID values.

Repeating loads of inplace-updated fields tends to cause bugs like the
one from the previous commit.  While there's no bug to fix in these code
sites, adopt the load-once style.  This improves the chance of future
copy/paste finding the safe style.

Discussion: https://postgr.es/m/20240423003956.e7.nmisch@google.com
This commit is contained in:
Noah Misch 2024-04-29 10:25:33 -07:00
parent f65ab862e3
commit dd0183469b
4 changed files with 34 additions and 21 deletions

View File

@ -5907,7 +5907,6 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
Page page; Page page;
BlockNumber block; BlockNumber block;
Buffer buffer; Buffer buffer;
TransactionId prune_xid;
Assert(ItemPointerIsValid(tid)); Assert(ItemPointerIsValid(tid));
@ -5960,11 +5959,16 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
* TransactionXmin, so there's no race here). * TransactionXmin, so there's no race here).
*/ */
Assert(TransactionIdIsValid(TransactionXmin)); Assert(TransactionIdIsValid(TransactionXmin));
if (TransactionIdPrecedes(TransactionXmin, relation->rd_rel->relfrozenxid)) {
prune_xid = relation->rd_rel->relfrozenxid; TransactionId relfrozenxid = relation->rd_rel->relfrozenxid;
else TransactionId prune_xid;
prune_xid = TransactionXmin;
PageSetPrunable(page, prune_xid); if (TransactionIdPrecedes(TransactionXmin, relfrozenxid))
prune_xid = relfrozenxid;
else
prune_xid = TransactionXmin;
PageSetPrunable(page, prune_xid);
}
/* store transaction information of xact deleting the tuple */ /* store transaction information of xact deleting the tuple */
tp.t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); tp.t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);

View File

@ -919,18 +919,24 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
* 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
* backwards, so take the max. * backwards, so take the max.
*/ */
if (TransactionIdIsValid(OldHeap->rd_rel->relfrozenxid) && {
TransactionIdPrecedes(cutoffs.FreezeLimit, TransactionId relfrozenxid = OldHeap->rd_rel->relfrozenxid;
OldHeap->rd_rel->relfrozenxid))
cutoffs.FreezeLimit = OldHeap->rd_rel->relfrozenxid; if (TransactionIdIsValid(relfrozenxid) &&
TransactionIdPrecedes(cutoffs.FreezeLimit, relfrozenxid))
cutoffs.FreezeLimit = relfrozenxid;
}
/* /*
* MultiXactCutoff, similarly, shouldn't go backwards either. * MultiXactCutoff, similarly, shouldn't go backwards either.
*/ */
if (MultiXactIdIsValid(OldHeap->rd_rel->relminmxid) && {
MultiXactIdPrecedes(cutoffs.MultiXactCutoff, MultiXactId relminmxid = OldHeap->rd_rel->relminmxid;
OldHeap->rd_rel->relminmxid))
cutoffs.MultiXactCutoff = OldHeap->rd_rel->relminmxid; if (MultiXactIdIsValid(relminmxid) &&
MultiXactIdPrecedes(cutoffs.MultiXactCutoff, relminmxid))
cutoffs.MultiXactCutoff = relminmxid;
}
/* /*
* Decide whether to use an indexscan or seqscan-and-optional-sort to scan * Decide whether to use an indexscan or seqscan-and-optional-sort to scan

View File

@ -1200,7 +1200,7 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
aggressiveXIDCutoff = nextXID - freeze_table_age; aggressiveXIDCutoff = nextXID - freeze_table_age;
if (!TransactionIdIsNormal(aggressiveXIDCutoff)) if (!TransactionIdIsNormal(aggressiveXIDCutoff))
aggressiveXIDCutoff = FirstNormalTransactionId; aggressiveXIDCutoff = FirstNormalTransactionId;
if (TransactionIdPrecedesOrEquals(rel->rd_rel->relfrozenxid, if (TransactionIdPrecedesOrEquals(cutoffs->relfrozenxid,
aggressiveXIDCutoff)) aggressiveXIDCutoff))
return true; return true;
@ -1221,7 +1221,7 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
aggressiveMXIDCutoff = nextMXID - multixact_freeze_table_age; aggressiveMXIDCutoff = nextMXID - multixact_freeze_table_age;
if (aggressiveMXIDCutoff < FirstMultiXactId) if (aggressiveMXIDCutoff < FirstMultiXactId)
aggressiveMXIDCutoff = FirstMultiXactId; aggressiveMXIDCutoff = FirstMultiXactId;
if (MultiXactIdPrecedesOrEquals(rel->rd_rel->relminmxid, if (MultiXactIdPrecedesOrEquals(cutoffs->relminmxid,
aggressiveMXIDCutoff)) aggressiveMXIDCutoff))
return true; return true;

View File

@ -2938,6 +2938,7 @@ relation_needs_vacanalyze(Oid relid,
int freeze_max_age; int freeze_max_age;
int multixact_freeze_max_age; int multixact_freeze_max_age;
TransactionId xidForceLimit; TransactionId xidForceLimit;
TransactionId relfrozenxid;
MultiXactId multiForceLimit; MultiXactId multiForceLimit;
Assert(classForm != NULL); Assert(classForm != NULL);
@ -2989,16 +2990,18 @@ relation_needs_vacanalyze(Oid relid,
xidForceLimit = recentXid - freeze_max_age; xidForceLimit = recentXid - freeze_max_age;
if (xidForceLimit < FirstNormalTransactionId) if (xidForceLimit < FirstNormalTransactionId)
xidForceLimit -= FirstNormalTransactionId; xidForceLimit -= FirstNormalTransactionId;
force_vacuum = (TransactionIdIsNormal(classForm->relfrozenxid) && relfrozenxid = classForm->relfrozenxid;
TransactionIdPrecedes(classForm->relfrozenxid, force_vacuum = (TransactionIdIsNormal(relfrozenxid) &&
xidForceLimit)); TransactionIdPrecedes(relfrozenxid, xidForceLimit));
if (!force_vacuum) if (!force_vacuum)
{ {
MultiXactId relminmxid = classForm->relminmxid;
multiForceLimit = recentMulti - multixact_freeze_max_age; multiForceLimit = recentMulti - multixact_freeze_max_age;
if (multiForceLimit < FirstMultiXactId) if (multiForceLimit < FirstMultiXactId)
multiForceLimit -= FirstMultiXactId; multiForceLimit -= FirstMultiXactId;
force_vacuum = MultiXactIdIsValid(classForm->relminmxid) && force_vacuum = MultiXactIdIsValid(relminmxid) &&
MultiXactIdPrecedes(classForm->relminmxid, multiForceLimit); MultiXactIdPrecedes(relminmxid, multiForceLimit);
} }
*wraparound = force_vacuum; *wraparound = force_vacuum;