mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
The rolled-back flag on serializable xacts was pointless and redundant with
the marked-for-death flag. It was only set for a fleeting moment while a transaction was being cleaned up at rollback. All the places that checked for the rolled-back flag should also check the marked-for-death flag, as both flags mean that the transaction will roll back. I also renamed the marked-for-death into "doomed", which is a lot shorter name.
This commit is contained in:
@ -244,9 +244,9 @@
|
|||||||
|
|
||||||
#define SxactIsOnFinishedList(sxact) (!SHMQueueIsDetached(&((sxact)->finishedLink)))
|
#define SxactIsOnFinishedList(sxact) (!SHMQueueIsDetached(&((sxact)->finishedLink)))
|
||||||
|
|
||||||
#define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
|
|
||||||
#define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
|
#define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
|
||||||
#define SxactIsRolledBack(sxact) (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 0)
|
#define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
|
||||||
|
#define SxactIsDoomed(sxact) (((sxact)->flags & SXACT_FLAG_DOOMED) != 0)
|
||||||
#define SxactIsReadOnly(sxact) (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0)
|
#define SxactIsReadOnly(sxact) (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0)
|
||||||
#define SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
|
#define SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
|
||||||
#define SxactHasSummaryConflictOut(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0)
|
#define SxactHasSummaryConflictOut(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0)
|
||||||
@ -259,7 +259,6 @@
|
|||||||
#define SxactIsDeferrableWaiting(sxact) (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)
|
#define SxactIsDeferrableWaiting(sxact) (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)
|
||||||
#define SxactIsROSafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0)
|
#define SxactIsROSafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0)
|
||||||
#define SxactIsROUnsafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)
|
#define SxactIsROUnsafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)
|
||||||
#define SxactIsMarkedForDeath(sxact) (((sxact)->flags & SXACT_FLAG_MARKED_FOR_DEATH) != 0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the hash code associated with a PREDICATELOCKTARGETTAG.
|
* Compute the hash code associated with a PREDICATELOCKTARGETTAG.
|
||||||
@ -609,8 +608,8 @@ RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
|
|||||||
Assert(reader != writer);
|
Assert(reader != writer);
|
||||||
|
|
||||||
/* Check the ends of the purported conflict first. */
|
/* Check the ends of the purported conflict first. */
|
||||||
if (SxactIsRolledBack(reader)
|
if (SxactIsDoomed(reader)
|
||||||
|| SxactIsRolledBack(writer)
|
|| SxactIsDoomed(writer)
|
||||||
|| SHMQueueEmpty(&reader->outConflicts)
|
|| SHMQueueEmpty(&reader->outConflicts)
|
||||||
|| SHMQueueEmpty(&writer->inConflicts))
|
|| SHMQueueEmpty(&writer->inConflicts))
|
||||||
return false;
|
return false;
|
||||||
@ -3048,7 +3047,7 @@ SetNewSxactGlobalXmin(void)
|
|||||||
|
|
||||||
for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
|
for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
|
||||||
{
|
{
|
||||||
if (!SxactIsRolledBack(sxact)
|
if (!SxactIsDoomed(sxact)
|
||||||
&& !SxactIsCommitted(sxact)
|
&& !SxactIsCommitted(sxact)
|
||||||
&& sxact != OldCommittedSxact)
|
&& sxact != OldCommittedSxact)
|
||||||
{
|
{
|
||||||
@ -3113,7 +3112,7 @@ ReleasePredicateLocks(const bool isCommit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(!isCommit || SxactIsPrepared(MySerializableXact));
|
Assert(!isCommit || SxactIsPrepared(MySerializableXact));
|
||||||
Assert(!SxactIsRolledBack(MySerializableXact));
|
Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
|
||||||
Assert(!SxactIsCommitted(MySerializableXact));
|
Assert(!SxactIsCommitted(MySerializableXact));
|
||||||
|
|
||||||
/* may not be serializable during COMMIT/ROLLBACK PREPARED */
|
/* may not be serializable during COMMIT/ROLLBACK PREPARED */
|
||||||
@ -3153,9 +3152,7 @@ ReleasePredicateLocks(const bool isCommit)
|
|||||||
MySerializableXact->flags |= SXACT_FLAG_READ_ONLY;
|
MySerializableXact->flags |= SXACT_FLAG_READ_ONLY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
MySerializableXact->flags |= SXACT_FLAG_DOOMED;
|
||||||
MySerializableXact->flags |= SXACT_FLAG_ROLLED_BACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!topLevelIsDeclaredReadOnly)
|
if (!topLevelIsDeclaredReadOnly)
|
||||||
{
|
{
|
||||||
@ -3531,7 +3528,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
|
|||||||
nextConflict;
|
nextConflict;
|
||||||
|
|
||||||
Assert(sxact != NULL);
|
Assert(sxact != NULL);
|
||||||
Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact));
|
Assert(SxactIsDoomed(sxact) || SxactIsCommitted(sxact));
|
||||||
Assert(LWLockHeldByMe(SerializableFinishedListLock));
|
Assert(LWLockHeldByMe(SerializableFinishedListLock));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3736,7 +3733,8 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
|
|||||||
if (!SerializationNeededForRead(relation, snapshot))
|
if (!SerializationNeededForRead(relation, snapshot))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SxactIsMarkedForDeath(MySerializableXact))
|
/* Check if someone else has already decided that we need to die */
|
||||||
|
if (SxactIsDoomed(MySerializableXact))
|
||||||
{
|
{
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
||||||
@ -3850,11 +3848,9 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
|
|||||||
}
|
}
|
||||||
sxact = sxid->myXact;
|
sxact = sxid->myXact;
|
||||||
Assert(TransactionIdEquals(sxact->topXid, xid));
|
Assert(TransactionIdEquals(sxact->topXid, xid));
|
||||||
if (sxact == MySerializableXact
|
if (sxact == MySerializableXact || SxactIsDoomed(sxact))
|
||||||
|| SxactIsRolledBack(sxact)
|
|
||||||
|| SxactIsMarkedForDeath(sxact))
|
|
||||||
{
|
{
|
||||||
/* We can't conflict with our own transaction or one rolled back. */
|
/* Can't conflict with ourself or a transaction that will roll back. */
|
||||||
LWLockRelease(SerializableXactHashLock);
|
LWLockRelease(SerializableXactHashLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3869,7 +3865,7 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
|
|||||||
{
|
{
|
||||||
if (!SxactIsPrepared(sxact))
|
if (!SxactIsPrepared(sxact))
|
||||||
{
|
{
|
||||||
sxact->flags |= SXACT_FLAG_MARKED_FOR_DEATH;
|
sxact->flags |= SXACT_FLAG_DOOMED;
|
||||||
LWLockRelease(SerializableXactHashLock);
|
LWLockRelease(SerializableXactHashLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3996,7 +3992,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
|
|||||||
mypredlocktag = predlock->tag;
|
mypredlocktag = predlock->tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!SxactIsRolledBack(sxact)
|
else if (!SxactIsDoomed(sxact)
|
||||||
&& (!SxactIsCommitted(sxact)
|
&& (!SxactIsCommitted(sxact)
|
||||||
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
|
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
|
||||||
sxact->finishedBefore))
|
sxact->finishedBefore))
|
||||||
@ -4009,7 +4005,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
|
|||||||
* Re-check after getting exclusive lock because the other
|
* Re-check after getting exclusive lock because the other
|
||||||
* transaction may have flagged a conflict.
|
* transaction may have flagged a conflict.
|
||||||
*/
|
*/
|
||||||
if (!SxactIsRolledBack(sxact)
|
if (!SxactIsDoomed(sxact)
|
||||||
&& (!SxactIsCommitted(sxact)
|
&& (!SxactIsCommitted(sxact)
|
||||||
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
|
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
|
||||||
sxact->finishedBefore))
|
sxact->finishedBefore))
|
||||||
@ -4113,7 +4109,8 @@ CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple,
|
|||||||
if (!SerializationNeededForWrite(relation))
|
if (!SerializationNeededForWrite(relation))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SxactIsMarkedForDeath(MySerializableXact))
|
/* Check if someone else has already decided that we need to die */
|
||||||
|
if (SxactIsDoomed(MySerializableXact))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
||||||
errmsg("could not serialize access due to read/write dependencies among transactions"),
|
errmsg("could not serialize access due to read/write dependencies among transactions"),
|
||||||
@ -4417,7 +4414,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader,
|
|||||||
{
|
{
|
||||||
SERIALIZABLEXACT *t0 = conflict->sxactOut;
|
SERIALIZABLEXACT *t0 = conflict->sxactOut;
|
||||||
|
|
||||||
if (!SxactIsRolledBack(t0)
|
if (!SxactIsDoomed(t0)
|
||||||
&& (!SxactIsCommitted(t0)
|
&& (!SxactIsCommitted(t0)
|
||||||
|| t0->commitSeqNo >= writer->commitSeqNo)
|
|| t0->commitSeqNo >= writer->commitSeqNo)
|
||||||
&& (!SxactIsReadOnly(t0)
|
&& (!SxactIsReadOnly(t0)
|
||||||
@ -4464,7 +4461,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader,
|
|||||||
errdetail("Cancelled on conflict out to pivot %u, during read.", writer->topXid),
|
errdetail("Cancelled on conflict out to pivot %u, during read.", writer->topXid),
|
||||||
errhint("The transaction might succeed if retried.")));
|
errhint("The transaction might succeed if retried.")));
|
||||||
}
|
}
|
||||||
writer->flags |= SXACT_FLAG_MARKED_FOR_DEATH;
|
writer->flags |= SXACT_FLAG_DOOMED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4496,7 +4493,8 @@ PreCommit_CheckForSerializationFailure(void)
|
|||||||
|
|
||||||
LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
|
LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
if (SxactIsMarkedForDeath(MySerializableXact))
|
/* Check if someone else has already decided that we need to die */
|
||||||
|
if (SxactIsDoomed(MySerializableXact))
|
||||||
{
|
{
|
||||||
LWLockRelease(SerializableXactHashLock);
|
LWLockRelease(SerializableXactHashLock);
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -4513,8 +4511,7 @@ PreCommit_CheckForSerializationFailure(void)
|
|||||||
while (nearConflict)
|
while (nearConflict)
|
||||||
{
|
{
|
||||||
if (!SxactIsCommitted(nearConflict->sxactOut)
|
if (!SxactIsCommitted(nearConflict->sxactOut)
|
||||||
&& !SxactIsRolledBack(nearConflict->sxactOut)
|
&& !SxactIsDoomed(nearConflict->sxactOut))
|
||||||
&& !SxactIsMarkedForDeath(nearConflict->sxactOut))
|
|
||||||
{
|
{
|
||||||
RWConflict farConflict;
|
RWConflict farConflict;
|
||||||
|
|
||||||
@ -4527,10 +4524,9 @@ PreCommit_CheckForSerializationFailure(void)
|
|||||||
if (farConflict->sxactOut == MySerializableXact
|
if (farConflict->sxactOut == MySerializableXact
|
||||||
|| (!SxactIsCommitted(farConflict->sxactOut)
|
|| (!SxactIsCommitted(farConflict->sxactOut)
|
||||||
&& !SxactIsReadOnly(farConflict->sxactOut)
|
&& !SxactIsReadOnly(farConflict->sxactOut)
|
||||||
&& !SxactIsRolledBack(farConflict->sxactOut)
|
&& !SxactIsDoomed(farConflict->sxactOut)))
|
||||||
&& !SxactIsMarkedForDeath(farConflict->sxactOut)))
|
|
||||||
{
|
{
|
||||||
nearConflict->sxactOut->flags |= SXACT_FLAG_MARKED_FOR_DEATH;
|
nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
farConflict = (RWConflict)
|
farConflict = (RWConflict)
|
||||||
|
@ -90,22 +90,21 @@ typedef struct SERIALIZABLEXACT
|
|||||||
int pid; /* pid of associated process */
|
int pid; /* pid of associated process */
|
||||||
} SERIALIZABLEXACT;
|
} SERIALIZABLEXACT;
|
||||||
|
|
||||||
#define SXACT_FLAG_ROLLED_BACK 0x00000001
|
#define SXACT_FLAG_COMMITTED 0x00000001 /* already committed */
|
||||||
#define SXACT_FLAG_COMMITTED 0x00000002
|
#define SXACT_FLAG_PREPARED 0x00000002 /* about to commit */
|
||||||
|
#define SXACT_FLAG_DOOMED 0x00000004 /* will roll back */
|
||||||
/*
|
/*
|
||||||
* The following flag actually means that the flagged transaction has a
|
* The following flag actually means that the flagged transaction has a
|
||||||
* conflict out *to a transaction which committed ahead of it*. It's hard
|
* conflict out *to a transaction which committed ahead of it*. It's hard
|
||||||
* to get that into a name of a reasonable length.
|
* to get that into a name of a reasonable length.
|
||||||
*/
|
*/
|
||||||
#define SXACT_FLAG_CONFLICT_OUT 0x00000004
|
#define SXACT_FLAG_CONFLICT_OUT 0x00000008
|
||||||
#define SXACT_FLAG_READ_ONLY 0x00000008
|
#define SXACT_FLAG_READ_ONLY 0x00000010
|
||||||
#define SXACT_FLAG_MARKED_FOR_DEATH 0x00000010
|
|
||||||
#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000020
|
#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000020
|
||||||
#define SXACT_FLAG_RO_SAFE 0x00000040
|
#define SXACT_FLAG_RO_SAFE 0x00000040
|
||||||
#define SXACT_FLAG_RO_UNSAFE 0x00000080
|
#define SXACT_FLAG_RO_UNSAFE 0x00000080
|
||||||
#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000100
|
#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000100
|
||||||
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000200
|
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000200
|
||||||
#define SXACT_FLAG_PREPARED 0x00000400
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following types are used to provide an ad hoc list for holding
|
* The following types are used to provide an ad hoc list for holding
|
||||||
|
Reference in New Issue
Block a user