From c2255595be2c9e75a1c3b6c2a4b7a2f16b82e85e Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Mon, 21 Dec 2020 20:44:11 -0800 Subject: [PATCH] Instrument heap_compute_xid_horizon_for_tuples(). --- src/backend/access/heap/heapam.c | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index a9583f3103..bb2488feb0 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6998,6 +6998,7 @@ heap_compute_xid_horizon_for_tuples(Relation rel, int nitems) { TransactionId latestRemovedXid = InvalidTransactionId; + TransactionId latestRemovedXidWithHotChain = InvalidTransactionId; BlockNumber hblkno; Buffer buf = InvalidBuffer; Page hpage; @@ -7092,6 +7093,36 @@ heap_compute_xid_horizon_for_tuples(Relation rel, hitemid = PageGetItemId(hpage, hoffnum); } + /* + * Instrumentation: follow HOT chain without changing function's + * behavior. + * + * Maybe latestRemovedXidWithHotChain instrumentation variable ends up + * ahead of authoritative latestRemovedXid value (which should not + * happen), and maybe the discrepancy makes the crucial difference for + * the operation as a whole (which could cause problems for hot + * standby during REDO of caller's record). + */ + if (ItemIdHasStorage(hitemid)) + { + ItemId hotitemid = hitemid; + HeapTupleHeader hothtuphdr; + + hothtuphdr = (HeapTupleHeader) PageGetItem(hpage, hotitemid); + while (HeapTupleHeaderIsHotUpdated(hothtuphdr)) + { + OffsetNumber hotoff = ItemPointerGetOffsetNumber(&hothtuphdr->t_ctid); + + hotitemid = PageGetItemId(hpage, hotoff); + if (!ItemIdHasStorage(hotitemid)) + break; + + hothtuphdr = (HeapTupleHeader) PageGetItem(hpage, hotitemid); + HeapTupleHeaderAdvanceLatestRemovedXid(hothtuphdr, + &latestRemovedXidWithHotChain); + } + } + /* * If the heap item has storage, then read the header and use that to * set latestRemovedXid. @@ -7134,6 +7165,13 @@ heap_compute_xid_horizon_for_tuples(Relation rel, * LP_DEAD, hence must already have generated a conflict. */ + if (TransactionIdPrecedes(latestRemovedXid, latestRemovedXidWithHotChain)) + elog(WARNING, "hot chain bug, latestRemovedXid: %u, latestRemovedXidWithHotChain: %u", + latestRemovedXid, latestRemovedXidWithHotChain); + else + elog(WARNING, "works okay this time, latestRemovedXid: %u, latestRemovedXidWithHotChain: %u", + latestRemovedXid, latestRemovedXidWithHotChain); + return latestRemovedXid; } -- 2.27.0