aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/pruneheap.c49
-rw-r--r--src/backend/access/heap/vacuumlazy.c3
-rw-r--r--src/include/access/heapam.h1
3 files changed, 40 insertions, 13 deletions
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 47b9e209154..c2c20d4b3bc 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -33,7 +33,8 @@ typedef struct
{
Relation rel;
- /* tuple visibility test, initialized for the relation */
+ /* State used to test tuple visibility; Initialized for the relation */
+ TransactionId oldest_xmin;
GlobalVisState *vistest;
/*
@@ -205,7 +206,8 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
int ndeleted,
nnewlpdead;
- ndeleted = heap_page_prune(relation, buffer, vistest, limited_xmin,
+ ndeleted = heap_page_prune(relation, buffer, InvalidTransactionId,
+ vistest, limited_xmin,
limited_ts, &nnewlpdead, NULL);
/*
@@ -247,11 +249,14 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
* also need to account for a reduction in the length of the line pointer
* array following array truncation by us.
*
- * 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 and oldest_xmin are used to distinguish whether tuples are DEAD or
+ * RECENTLY_DEAD (see heap_prune_satisfies_vacuum and
+ * HeapTupleSatisfiesVacuum). If oldest_xmin is provided by the caller, it is
+ * used before consulting GlobalVisState.
+ *
+ * old_snap_xmin / old_snap_ts need to either have been set by
+ * TransactionIdLimitedForOldSnapshots, or InvalidTransactionId/0
+ * respectively.
*
* Sets *nnewlpdead for caller, indicating the number of items that were
* newly set LP_DEAD during prune operation.
@@ -263,6 +268,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
*/
int
heap_page_prune(Relation relation, Buffer buffer,
+ TransactionId oldest_xmin,
GlobalVisState *vistest,
TransactionId old_snap_xmin,
TimestampTz old_snap_ts,
@@ -290,6 +296,7 @@ heap_page_prune(Relation relation, Buffer buffer,
*/
prstate.new_prune_xid = InvalidTransactionId;
prstate.rel = relation;
+ prstate.oldest_xmin = oldest_xmin;
prstate.vistest = vistest;
prstate.old_snap_xmin = old_snap_xmin;
prstate.old_snap_ts = old_snap_ts;
@@ -520,13 +527,31 @@ 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.
+ * For VACUUM, we must be sure to prune tuples with xmax older than
+ * oldest_xmin -- a visibility cutoff determined at the beginning of
+ * vacuuming the relation. oldest_xmin is used for freezing determination
+ * and we cannot freeze dead tuples' xmaxes.
+ */
+ if (TransactionIdIsValid(prstate->oldest_xmin) &&
+ NormalTransactionIdPrecedes(dead_after, prstate->oldest_xmin))
+ return HEAPTUPLE_DEAD;
+
+ /*
+ * Determine whether or not the tuple is considered dead when compared
+ * with the provided GlobalVisState. On-access pruning does not provide
+ * oldest_xmin. And for vacuum, even if the tuple's xmax is not older than
+ * oldest_xmin, GlobalVisTestIsRemovableXid() could find the row dead if
+ * the GlobalVisState has been updated since the beginning of vacuuming
+ * the relation.
*/
if (GlobalVisTestIsRemovableXid(prstate->vistest, dead_after))
- res = HEAPTUPLE_DEAD;
- else if (OldSnapshotThresholdActive())
+ return HEAPTUPLE_DEAD;
+
+ /*
+ * If GlobalVisTestIsRemovableXid() is not sufficient to find the row dead
+ * and old_snapshot_threshold is enabled, try to use the lowered horizon.
+ */
+ if (OldSnapshotThresholdActive())
{
/* haven't determined limited horizon yet, requests */
if (!TransactionIdIsValid(prstate->old_snap_xmin))
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index c474b061146..9fa88960ada 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -1581,7 +1581,8 @@ 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, vacrel->vistest,
+ tuples_deleted = heap_page_prune(rel, buf, vacrel->cutoffs.OldestXmin,
+ vacrel->vistest,
InvalidTransactionId, 0, &nnewlpdead,
&vacrel->offnum);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index faf50265191..c7278219b24 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -285,6 +285,7 @@ extern TransactionId heap_index_delete_tuples(Relation rel,
struct GlobalVisState;
extern void heap_page_prune_opt(Relation relation, Buffer buffer);
extern int heap_page_prune(Relation relation, Buffer buffer,
+ TransactionId oldest_xmin,
struct GlobalVisState *vistest,
TransactionId old_snap_xmin,
TimestampTz old_snap_ts,