From 23036ff6bad6a50574dac7f398fcdf9f171f7120 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Sat, 6 Jan 2024 16:22:17 -0500 Subject: [PATCH v4 06/19] Add reference to VacuumCutoffs in HeapPageFreeze Future commits will move opportunistic freezing into the main path of pruning in heap_page_prune(). Because on-access pruning will not do opportunistic freezing, it is cleaner to keep the visibility information required for calling heap_prepare_freeze_tuple() inside of the HeapPageFreeze structure itself by saving a reference to VacuumCutoffs. --- src/backend/access/heap/heapam.c | 67 ++++++++++++++-------------- src/backend/access/heap/vacuumlazy.c | 3 +- src/include/access/heapam.h | 2 +- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 34bc60f625f..7261c4988d7 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6023,7 +6023,7 @@ heap_inplace_update(Relation relation, HeapTuple tuple) */ static TransactionId FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, - const struct VacuumCutoffs *cutoffs, uint16 *flags, + uint16 *flags, HeapPageFreeze *pagefrz) { TransactionId newxmax; @@ -6049,12 +6049,12 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, pagefrz->freeze_required = true; return InvalidTransactionId; } - else if (MultiXactIdPrecedes(multi, cutoffs->relminmxid)) + else if (MultiXactIdPrecedes(multi, pagefrz->cutoffs->relminmxid)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("found multixact %u from before relminmxid %u", - multi, cutoffs->relminmxid))); - else if (MultiXactIdPrecedes(multi, cutoffs->OldestMxact)) + multi, pagefrz->cutoffs->relminmxid))); + else if (MultiXactIdPrecedes(multi, pagefrz->cutoffs->OldestMxact)) { TransactionId update_xact; @@ -6069,7 +6069,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("multixact %u from before multi freeze cutoff %u found to be still running", - multi, cutoffs->OldestMxact))); + multi, pagefrz->cutoffs->OldestMxact))); if (HEAP_XMAX_IS_LOCKED_ONLY(t_infomask)) { @@ -6080,13 +6080,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, /* replace multi with single XID for its updater? */ update_xact = MultiXactIdGetUpdateXid(multi, t_infomask); - if (TransactionIdPrecedes(update_xact, cutoffs->relfrozenxid)) + if (TransactionIdPrecedes(update_xact, pagefrz->cutoffs->relfrozenxid)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("multixact %u contains update XID %u from before relfrozenxid %u", multi, update_xact, - cutoffs->relfrozenxid))); - else if (TransactionIdPrecedes(update_xact, cutoffs->OldestXmin)) + pagefrz->cutoffs->relfrozenxid))); + else if (TransactionIdPrecedes(update_xact, pagefrz->cutoffs->OldestXmin)) { /* * Updater XID has to have aborted (otherwise the tuple would have @@ -6098,7 +6098,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("multixact %u contains committed update XID %u from before removable cutoff %u", multi, update_xact, - cutoffs->OldestXmin))); + pagefrz->cutoffs->OldestXmin))); *flags |= FRM_INVALIDATE_XMAX; pagefrz->freeze_required = true; return InvalidTransactionId; @@ -6150,9 +6150,9 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, { TransactionId xid = members[i].xid; - Assert(!TransactionIdPrecedes(xid, cutoffs->relfrozenxid)); + Assert(!TransactionIdPrecedes(xid, pagefrz->cutoffs->relfrozenxid)); - if (TransactionIdPrecedes(xid, cutoffs->FreezeLimit)) + if (TransactionIdPrecedes(xid, pagefrz->cutoffs->FreezeLimit)) { /* Can't violate the FreezeLimit postcondition */ need_replace = true; @@ -6164,7 +6164,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, /* Can't violate the MultiXactCutoff postcondition, either */ if (!need_replace) - need_replace = MultiXactIdPrecedes(multi, cutoffs->MultiXactCutoff); + need_replace = MultiXactIdPrecedes(multi, pagefrz->cutoffs->MultiXactCutoff); if (!need_replace) { @@ -6203,7 +6203,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, TransactionId xid = members[i].xid; MultiXactStatus mstatus = members[i].status; - Assert(!TransactionIdPrecedes(xid, cutoffs->relfrozenxid)); + Assert(!TransactionIdPrecedes(xid, pagefrz->cutoffs->relfrozenxid)); if (!ISUPDATE_from_mxstatus(mstatus)) { @@ -6214,12 +6214,12 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, if (TransactionIdIsCurrentTransactionId(xid) || TransactionIdIsInProgress(xid)) { - if (TransactionIdPrecedes(xid, cutoffs->OldestXmin)) + if (TransactionIdPrecedes(xid, pagefrz->cutoffs->OldestXmin)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("multixact %u contains running locker XID %u from before removable cutoff %u", multi, xid, - cutoffs->OldestXmin))); + pagefrz->cutoffs->OldestXmin))); newmembers[nnewmembers++] = members[i]; has_lockers = true; } @@ -6277,11 +6277,11 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, * We determined that updater must be kept -- add it to pending new * members list */ - if (TransactionIdPrecedes(xid, cutoffs->OldestXmin)) + if (TransactionIdPrecedes(xid, pagefrz->cutoffs->OldestXmin)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("multixact %u contains committed update XID %u from before removable cutoff %u", - multi, xid, cutoffs->OldestXmin))); + multi, xid, pagefrz->cutoffs->OldestXmin))); newmembers[nnewmembers++] = members[i]; } @@ -6373,7 +6373,6 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, */ bool heap_prepare_freeze_tuple(HeapTupleHeader tuple, - const struct VacuumCutoffs *cutoffs, HeapPageFreeze *pagefrz, HeapTupleFreeze *frz, bool *totally_frozen) { @@ -6401,14 +6400,14 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, xmin_already_frozen = true; else { - if (TransactionIdPrecedes(xid, cutoffs->relfrozenxid)) + if (TransactionIdPrecedes(xid, pagefrz->cutoffs->relfrozenxid)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("found xmin %u from before relfrozenxid %u", - xid, cutoffs->relfrozenxid))); + xid, pagefrz->cutoffs->relfrozenxid))); /* Will set freeze_xmin flags in freeze plan below */ - freeze_xmin = TransactionIdPrecedes(xid, cutoffs->OldestXmin); + freeze_xmin = TransactionIdPrecedes(xid, pagefrz->cutoffs->OldestXmin); /* Verify that xmin committed if and when freeze plan is executed */ if (freeze_xmin) @@ -6422,8 +6421,8 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, xid = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsNormal(xid)) { - Assert(TransactionIdPrecedesOrEquals(cutoffs->relfrozenxid, xid)); - Assert(TransactionIdPrecedes(xid, cutoffs->OldestXmin)); + Assert(TransactionIdPrecedesOrEquals(pagefrz->cutoffs->relfrozenxid, xid)); + Assert(TransactionIdPrecedes(xid, pagefrz->cutoffs->OldestXmin)); /* * For Xvac, we always freeze proactively. This allows totally_frozen @@ -6448,8 +6447,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, * perform no-op xmax processing. The only constraint is that the * FreezeLimit/MultiXactCutoff postcondition must never be violated. */ - newxmax = FreezeMultiXactId(xid, tuple->t_infomask, cutoffs, - &flags, pagefrz); + newxmax = FreezeMultiXactId(xid, tuple->t_infomask, &flags, pagefrz); if (flags & FRM_NOOP) { @@ -6472,7 +6470,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, * (This repeats work from FreezeMultiXactId, but allows "no * freeze" tracker maintenance to happen in only one place.) */ - Assert(!MultiXactIdPrecedes(newxmax, cutoffs->MultiXactCutoff)); + Assert(!MultiXactIdPrecedes(newxmax, pagefrz->cutoffs->MultiXactCutoff)); Assert(MultiXactIdIsValid(newxmax) && xid == newxmax); } else if (flags & FRM_RETURN_IS_XID) @@ -6481,7 +6479,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, * xmax will become an updater Xid (original MultiXact's updater * member Xid will be carried forward as a simple Xid in Xmax). */ - Assert(!TransactionIdPrecedes(newxmax, cutoffs->OldestXmin)); + Assert(!TransactionIdPrecedes(newxmax, pagefrz->cutoffs->OldestXmin)); /* * NB -- some of these transformations are only valid because we @@ -6505,7 +6503,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, * xmax is an old MultiXactId that we have to replace with a new * MultiXactId, to carry forward two or more original member XIDs. */ - Assert(!MultiXactIdPrecedes(newxmax, cutoffs->OldestMxact)); + Assert(!MultiXactIdPrecedes(newxmax, pagefrz->cutoffs->OldestMxact)); /* * We can't use GetMultiXactIdHintBits directly on the new multi @@ -6540,14 +6538,14 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, else if (TransactionIdIsNormal(xid)) { /* Raw xmax is normal XID */ - if (TransactionIdPrecedes(xid, cutoffs->relfrozenxid)) + if (TransactionIdPrecedes(xid, pagefrz->cutoffs->relfrozenxid)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("found xmax %u from before relfrozenxid %u", - xid, cutoffs->relfrozenxid))); + xid, pagefrz->cutoffs->relfrozenxid))); /* Will set freeze_xmax flags in freeze plan below */ - freeze_xmax = TransactionIdPrecedes(xid, cutoffs->OldestXmin); + freeze_xmax = TransactionIdPrecedes(xid, pagefrz->cutoffs->OldestXmin); /* * Verify that xmax aborted if and when freeze plan is executed, @@ -6627,7 +6625,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, * Does this tuple force caller to freeze the entire page? */ pagefrz->freeze_required = - heap_tuple_should_freeze(tuple, cutoffs, + heap_tuple_should_freeze(tuple, pagefrz->cutoffs, &pagefrz->NoFreezePageRelfrozenXid, &pagefrz->NoFreezePageRelminMxid); } @@ -6949,8 +6947,9 @@ heap_freeze_tuple(HeapTupleHeader tuple, pagefrz.NoFreezePageRelfrozenXid = FreezeLimit; pagefrz.NoFreezePageRelminMxid = MultiXactCutoff; - do_freeze = heap_prepare_freeze_tuple(tuple, &cutoffs, - &pagefrz, &frz, &totally_frozen); + pagefrz.cutoffs = &cutoffs; + + do_freeze = heap_prepare_freeze_tuple(tuple, &pagefrz, &frz, &totally_frozen); /* * Note that because this is not a WAL-logged operation, we don't need to diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index f9892f4cd08..06e0e841582 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1442,6 +1442,7 @@ lazy_scan_prune(LVRelState *vacrel, pagefrz.FreezePageRelminMxid = vacrel->NewRelminMxid; pagefrz.NoFreezePageRelfrozenXid = vacrel->NewRelfrozenXid; pagefrz.NoFreezePageRelminMxid = vacrel->NewRelminMxid; + pagefrz.cutoffs = &vacrel->cutoffs; tuples_frozen = 0; lpdead_items = 0; live_tuples = 0; @@ -1587,7 +1588,7 @@ lazy_scan_prune(LVRelState *vacrel, hastup = true; /* page makes rel truncation unsafe */ /* Tuple with storage -- consider need to freeze */ - if (heap_prepare_freeze_tuple(htup, &vacrel->cutoffs, &pagefrz, + if (heap_prepare_freeze_tuple(htup, &pagefrz, &frozen[tuples_frozen], &totally_frozen)) { /* Save prepared freeze plan for later */ diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index d8e65ae7e35..297ba03bf09 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -189,6 +189,7 @@ typedef struct HeapPageFreeze TransactionId NoFreezePageRelfrozenXid; MultiXactId NoFreezePageRelminMxid; + struct VacuumCutoffs *cutoffs; } HeapPageFreeze; /* @@ -295,7 +296,6 @@ extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple, extern void heap_inplace_update(Relation relation, HeapTuple tuple); extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple, - const struct VacuumCutoffs *cutoffs, HeapPageFreeze *pagefrz, HeapTupleFreeze *frz, bool *totally_frozen); extern void heap_freeze_execute_prepared(Relation rel, Buffer buffer, -- 2.40.1