Page page;
BlockNumber block;
Buffer buffer;
+ TransactionId prune_xid;
Assert(ItemPointerIsValid(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);