aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/heap/heapam.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 94eb37d48d2..9756bf98bde 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -9007,6 +9007,10 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
* while it is visible to us. The "visible" bool indicates whether the
* tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
* is going on with it.
+ *
+ * In the event of a concurrently inserted tuple that also happens to have
+ * been concurrently updated (by a separate transaction), the xmin of the
+ * tuple will be used -- not the updater's xid.
*/
htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
switch (htsvResult)
@@ -9017,17 +9021,24 @@ HeapCheckForSerializableConflictOut(bool visible, Relation relation,
xid = HeapTupleHeaderGetXmin(tuple->t_data);
break;
case HEAPTUPLE_RECENTLY_DEAD:
- if (!visible)
- return;
- xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
- break;
case HEAPTUPLE_DELETE_IN_PROGRESS:
- xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
+ if (visible)
+ xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
+ else
+ xid = HeapTupleHeaderGetXmin(tuple->t_data);
+
+ if (TransactionIdPrecedes(xid, TransactionXmin))
+ {
+ /* This is like the HEAPTUPLE_DEAD case */
+ Assert(!visible);
+ return;
+ }
break;
case HEAPTUPLE_INSERT_IN_PROGRESS:
xid = HeapTupleHeaderGetXmin(tuple->t_data);
break;
case HEAPTUPLE_DEAD:
+ Assert(!visible);
return;
default: