From 33ec54d05441183ba908a728186b2a6751bc4cf5 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Mon, 13 May 2024 10:27:50 -0400 Subject: [PATCH v1] Fix vacuum hang --- src/backend/access/heap/pruneheap.c | 33 ++++++++++++++++++++-------- src/backend/access/heap/vacuumlazy.c | 2 +- src/include/access/heapam.h | 1 + 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index f7f8056d631..0356391c5db 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -35,6 +35,12 @@ typedef struct /* tuple visibility test, initialized for the relation */ GlobalVisState *vistest; + /* + * Used only by vacuum. The oldest xmin at the beginning of vacuuming the + * relation. + */ + TransactionId oldest_xmin; + /* * Thresholds set by TransactionIdLimitedForOldSnapshots() if they have * been computed (done on demand, and only if @@ -203,6 +209,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer) { /* OK to prune */ (void) heap_page_prune(relation, buffer, vistest, + InvalidTransactionId, limited_xmin, limited_ts, true, NULL); } @@ -218,11 +225,14 @@ heap_page_prune_opt(Relation relation, Buffer buffer) * * Caller must have pin and buffer cleanup lock on the page. * - * vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD - * (see heap_prune_satisfies_vacuum and - * HeapTupleSatisfiesVacuum). old_snap_xmin / old_snap_ts need to - * either have been set by TransactionIdLimitedForOldSnapshots, or - * InvalidTransactionId/0 respectively. + * vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD (see + * heap_prune_satisfies_vacuum and HeapTupleSatisfiesVacuum). + * + * oldest_xmin is only set to a valid TransactionId by vacuum. It is the oldest + * removable TransactionId at the beginning of vacuuming the relation. + * + * old_snap_xmin / old_snap_ts need to either have been set by + * TransactionIdLimitedForOldSnapshots, or InvalidTransactionId/0 respectively. * * If report_stats is true then we send the number of reclaimed heap-only * tuples to pgstats. (This must be false during vacuum, since vacuum will @@ -237,6 +247,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer) int heap_page_prune(Relation relation, Buffer buffer, GlobalVisState *vistest, + TransactionId oldest_xmin, TransactionId old_snap_xmin, TimestampTz old_snap_ts, bool report_stats, @@ -263,6 +274,7 @@ heap_page_prune(Relation relation, Buffer buffer, prstate.new_prune_xid = InvalidTransactionId; prstate.rel = relation; prstate.vistest = vistest; + prstate.oldest_xmin = oldest_xmin; prstate.old_snap_xmin = old_snap_xmin; prstate.old_snap_ts = old_snap_ts; prstate.old_snap_used = false; @@ -512,11 +524,14 @@ heap_prune_satisfies_vacuum(PruneState *prstate, HeapTuple tup, Buffer buffer) } /* - * First check if GlobalVisTestIsRemovableXid() is sufficient to find the - * row dead. If not, and old_snapshot_threshold is enabled, try to use the - * lowered horizon. + * First check if oldest_xmin or GlobalVisTestIsRemovableXid() is + * sufficient to find the row dead. If not, and old_snapshot_threshold is + * enabled, try to use the lowered horizon. */ - if (GlobalVisTestIsRemovableXid(prstate->vistest, dead_after)) + if (TransactionIdIsValid(prstate->oldest_xmin) && + NormalTransactionIdPrecedes(dead_after, prstate->oldest_xmin)) + res = HEAPTUPLE_DEAD; + else if (GlobalVisTestIsRemovableXid(prstate->vistest, dead_after)) res = HEAPTUPLE_DEAD; else if (OldSnapshotThresholdActive()) { diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 8aab6e324e0..31fdc8e6cd9 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1738,7 +1738,7 @@ retry: * lpdead_items's final value can be thought of as the number of tuples * that were deleted from indexes. */ - tuples_deleted = heap_page_prune(rel, buf, vistest, + tuples_deleted = heap_page_prune(rel, buf, vistest, vacrel->OldestXmin, InvalidTransactionId, 0, false, &vacrel->offnum); diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 4f1dff9ca1b..780b30fe74c 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -187,6 +187,7 @@ struct GlobalVisState; extern void heap_page_prune_opt(Relation relation, Buffer buffer); extern int heap_page_prune(Relation relation, Buffer buffer, struct GlobalVisState *vistest, + TransactionId oldest_xmin, TransactionId old_snap_xmin, TimestampTz old_snap_ts_ts, bool report_stats, -- 2.34.1