summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c3
-rw-r--r--src/backend/utils/time/tqual.c40
-rw-r--r--src/include/utils/tqual.h2
3 files changed, 43 insertions, 2 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 3259354d5e0..7e4c8f52ab2 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1609,8 +1609,7 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
* transactions.
*/
if (all_dead && *all_dead &&
- HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin,
- buffer) != HEAPTUPLE_DEAD)
+ !HeapTupleIsSurelyDead(heapTuple->t_data, RecentGlobalXmin))
*all_dead = false;
/*
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index c1c78c389cb..727e0bf91bf 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -1219,6 +1219,46 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
return HEAPTUPLE_DEAD;
}
+/*
+ * HeapTupleIsSurelyDead
+ *
+ * Determine whether a tuple is surely dead. We sometimes use this
+ * in lieu of HeapTupleSatisifesVacuum when the tuple has just been
+ * tested by HeapTupleSatisfiesMVCC and, therefore, any hint bits that
+ * can be set should already be set. We assume that if no hint bits
+ * either for xmin or xmax, the transaction is still running. This is
+ * therefore faster than HeapTupleSatisfiesVacuum, because we don't
+ * consult CLOG (and also because we don't need to give an exact answer,
+ * just whether or not the tuple is surely dead).
+ */
+bool
+HeapTupleIsSurelyDead(HeapTupleHeader tuple, TransactionId OldestXmin)
+{
+ /*
+ * If the inserting transaction is marked invalid, then it aborted,
+ * and the tuple is definitely dead. If it's marked neither committed
+ * nor invalid, then we assume it's still alive (since the presumption
+ * is that all relevant hint bits were just set moments ago).
+ */
+ if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
+ return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false;
+
+ /*
+ * If the inserting transaction committed, but any deleting transaction
+ * aborted, the tuple is still alive. Likewise, if XMAX is a lock rather
+ * than a delete, the tuple is still alive.
+ */
+ if (tuple->t_infomask &
+ (HEAP_XMAX_INVALID | HEAP_IS_LOCKED | HEAP_XMAX_IS_MULTI))
+ return false;
+
+ /* If deleter isn't known to have committed, assume it's still running. */
+ if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
+ return false;
+
+ /* Deleter committed, so tuple is dead if the XID is old enough. */
+ return TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin);
+}
/*
* XidInMVCCSnapshot
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index 0f8a7f8c2d2..3d8a480d810 100644
--- a/src/include/utils/tqual.h
+++ b/src/include/utils/tqual.h
@@ -83,6 +83,8 @@ extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
CommandId curcid, Buffer buffer);
extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
TransactionId OldestXmin, Buffer buffer);
+extern bool HeapTupleIsSurelyDead(HeapTupleHeader tuple,
+ TransactionId OldestXmin);
extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
uint16 infomask, TransactionId xid);