aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a25d539ec47..c4a5aa616a3 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -5581,6 +5581,7 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
Page page;
BlockNumber block;
Buffer buffer;
+ TransactionId prune_xid;
Assert(ItemPointerIsValid(tid));
@@ -5623,13 +5624,21 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
START_CRIT_SECTION();
/*
- * The tuple will become DEAD immediately. Flag that this page
- * immediately is a candidate for pruning by setting xmin to
- * RecentGlobalXmin. That's not pretty, but it doesn't seem worth
- * inventing a nicer API for this.
+ * The tuple will become DEAD immediately. Flag that this page is a
+ * candidate for pruning by setting xmin to TransactionXmin. While not
+ * immediately prunable, it is the oldest xid we can cheaply determine
+ * that's safe against wraparound / being older than the table's
+ * relfrozenxid. To defend against the unlikely case of a new relation
+ * having a newer relfrozenxid than our TransactionXmin, use relfrozenxid
+ * if so (vacuum can't subsequently move relfrozenxid to beyond
+ * TransactionXmin, so there's no race here).
*/
- Assert(TransactionIdIsValid(RecentGlobalXmin));
- PageSetPrunable(page, RecentGlobalXmin);
+ Assert(TransactionIdIsValid(TransactionXmin));
+ if (TransactionIdPrecedes(TransactionXmin, relation->rd_rel->relfrozenxid))
+ prune_xid = relation->rd_rel->relfrozenxid;
+ else
+ prune_xid = TransactionXmin;
+ PageSetPrunable(page, prune_xid);
/* store transaction information of xact deleting the tuple */
tp.t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);