Skip to content

Commit 0e708d3

Browse files
committed
Use TransactionXmin instead of RecentGlobalXmin in heap_abort_speculative().
There's a very low risk that RecentGlobalXmin could be far enough in the past to be older than relfrozenxid, or even wrapped around. Luckily the consequences of that having happened wouldn't be too bad - the page wouldn't be pruned for a while. Avoid that risk by using TransactionXmin instead. As that's announced via MyPgXact->xmin, it is protected against wrapping around (see code comments for details around relfrozenxid). Author: Andres Freund Discussion: https://postgr.es/m/20200328213023.s4eyijhdosuc4vcj@alap3.anarazel.de Backpatch: 9.5-
1 parent 038c9bb commit 0e708d3

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

src/backend/access/heap/heapam.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6126,6 +6126,7 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
61266126
Page page;
61276127
BlockNumber block;
61286128
Buffer buffer;
6129+
TransactionId prune_xid;
61296130

61306131
Assert(ItemPointerIsValid(tid));
61316132

@@ -6168,13 +6169,21 @@ heap_abort_speculative(Relation relation, HeapTuple tuple)
61686169
START_CRIT_SECTION();
61696170

61706171
/*
6171-
* The tuple will become DEAD immediately. Flag that this page
6172-
* immediately is a candidate for pruning by setting xmin to
6173-
* RecentGlobalXmin. That's not pretty, but it doesn't seem worth
6174-
* inventing a nicer API for this.
6172+
* The tuple will become DEAD immediately. Flag that this page is a
6173+
* candidate for pruning by setting xmin to TransactionXmin. While not
6174+
* immediately prunable, it is the oldest xid we can cheaply determine
6175+
* that's safe against wraparound / being older than the table's
6176+
* relfrozenxid. To defend against the unlikely case of a new relation
6177+
* having a newer relfrozenxid than our TransactionXmin, use relfrozenxid
6178+
* if so (vacuum can't subsequently move relfrozenxid to beyond
6179+
* TransactionXmin, so there's no race here).
61756180
*/
6176-
Assert(TransactionIdIsValid(RecentGlobalXmin));
6177-
PageSetPrunable(page, RecentGlobalXmin);
6181+
Assert(TransactionIdIsValid(TransactionXmin));
6182+
if (TransactionIdPrecedes(TransactionXmin, relation->rd_rel->relfrozenxid))
6183+
prune_xid = relation->rd_rel->relfrozenxid;
6184+
else
6185+
prune_xid = TransactionXmin;
6186+
PageSetPrunable(page, prune_xid);
61786187

61796188
/* store transaction information of xact deleting the tuple */
61806189
tp.t_data->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED);

0 commit comments

Comments
 (0)