*/
needToClear = false;
LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
- if (MySerializableXact->xmin == SerializableGlobalXmin)
+ if (TransactionIdEquals(MySerializableXact->xmin, SerializableGlobalXmin))
{
Assert(SerializableGlobalXminCount > 0);
if (--SerializableGlobalXminCount == 0)
xid = HeapTupleHeaderGetXmin(tuple->t_data);
}
- /* Bail out if xid is too early to be a conflict. */
+ /*
+ * Find top level xid. Bail out if xid is too early to be a conflict.
+ */
if (TransactionIdPrecedes(xid, TransactionXmin))
return;
xid = SubTransGetTopmostTransaction(xid);
failure = false;
+ /*
+ * Check for already-committed writer with rw-conflict out flagged.
+ * This means that the reader must immediately fail.
+ */
+ if (SxactIsCommitted(writer) && (writer->flags & SXACT_FLAG_CONFLICT_OUT))
+ failure = true;
+
/*
* Check whether the reader has become a pivot with a committed writer.
* If so, we must roll back unless every in-conflict either committed
* before the writer committed or is READ ONLY and overlaps the writer.
*/
- if (SxactIsCommitted(writer) && !SxactIsReadOnly(reader))
+ if (!failure && SxactIsCommitted(writer) && !SxactIsReadOnly(reader))
{
conflict = (RWConflict)
SHMQueueNext(&reader->inConflicts,
{
if (!SxactIsRolledBack(conflict->sxactIn)
&& (!SxactIsCommitted(conflict->sxactIn)
- || conflict->sxactIn->commitSeqNo > writer->commitSeqNo)
+ || conflict->sxactIn->commitSeqNo >= writer->commitSeqNo)
&& (!SxactIsReadOnly(conflict->sxactIn)
|| conflict->sxactIn->lastCommitBeforeSnapshot >= writer->commitSeqNo))
{