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:
Heikki Linnakangas 2011-06-15 13:35:28 +03:00
parent 0a0e2b52a5
commit 264a6b127a
2 changed files with 29 additions and 34 deletions

View File

@ -244,9 +244,9 @@
#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 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 SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 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 SxactIsROSafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 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.
@ -609,8 +608,8 @@ RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Assert(reader != writer);
/* Check the ends of the purported conflict first. */
if (SxactIsRolledBack(reader)
|| SxactIsRolledBack(writer)
if (SxactIsDoomed(reader)
|| SxactIsDoomed(writer)
|| SHMQueueEmpty(&reader->outConflicts)
|| SHMQueueEmpty(&writer->inConflicts))
return false;
@ -3048,7 +3047,7 @@ SetNewSxactGlobalXmin(void)
for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
{
if (!SxactIsRolledBack(sxact)
if (!SxactIsDoomed(sxact)
&& !SxactIsCommitted(sxact)
&& sxact != OldCommittedSxact)
{
@ -3113,7 +3112,7 @@ ReleasePredicateLocks(const bool isCommit)
}
Assert(!isCommit || SxactIsPrepared(MySerializableXact));
Assert(!SxactIsRolledBack(MySerializableXact));
Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
Assert(!SxactIsCommitted(MySerializableXact));
/* may not be serializable during COMMIT/ROLLBACK PREPARED */
@ -3153,9 +3152,7 @@ ReleasePredicateLocks(const bool isCommit)
MySerializableXact->flags |= SXACT_FLAG_READ_ONLY;
}
else
{
MySerializableXact->flags |= SXACT_FLAG_ROLLED_BACK;
}
MySerializableXact->flags |= SXACT_FLAG_DOOMED;
if (!topLevelIsDeclaredReadOnly)
{
@ -3531,7 +3528,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
nextConflict;
Assert(sxact != NULL);
Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact));
Assert(SxactIsDoomed(sxact) || SxactIsCommitted(sxact));
Assert(LWLockHeldByMe(SerializableFinishedListLock));
/*
@ -3736,7 +3733,8 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
if (!SerializationNeededForRead(relation, snapshot))
return;
if (SxactIsMarkedForDeath(MySerializableXact))
/* Check if someone else has already decided that we need to die */
if (SxactIsDoomed(MySerializableXact))
{
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
@ -3850,11 +3848,9 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
}
sxact = sxid->myXact;
Assert(TransactionIdEquals(sxact->topXid, xid));
if (sxact == MySerializableXact
|| SxactIsRolledBack(sxact)
|| SxactIsMarkedForDeath(sxact))
if (sxact == MySerializableXact || SxactIsDoomed(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);
return;
}
@ -3869,7 +3865,7 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
{
if (!SxactIsPrepared(sxact))
{
sxact->flags |= SXACT_FLAG_MARKED_FOR_DEATH;
sxact->flags |= SXACT_FLAG_DOOMED;
LWLockRelease(SerializableXactHashLock);
return;
}
@ -3996,7 +3992,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
mypredlocktag = predlock->tag;
}
}
else if (!SxactIsRolledBack(sxact)
else if (!SxactIsDoomed(sxact)
&& (!SxactIsCommitted(sxact)
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
sxact->finishedBefore))
@ -4009,7 +4005,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
* Re-check after getting exclusive lock because the other
* transaction may have flagged a conflict.
*/
if (!SxactIsRolledBack(sxact)
if (!SxactIsDoomed(sxact)
&& (!SxactIsCommitted(sxact)
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
sxact->finishedBefore))
@ -4113,7 +4109,8 @@ CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple,
if (!SerializationNeededForWrite(relation))
return;
if (SxactIsMarkedForDeath(MySerializableXact))
/* Check if someone else has already decided that we need to die */
if (SxactIsDoomed(MySerializableXact))
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
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;
if (!SxactIsRolledBack(t0)
if (!SxactIsDoomed(t0)
&& (!SxactIsCommitted(t0)
|| t0->commitSeqNo >= writer->commitSeqNo)
&& (!SxactIsReadOnly(t0)
@ -4464,7 +4461,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader,
errdetail("Cancelled on conflict out to pivot %u, during read.", writer->topXid),
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);
if (SxactIsMarkedForDeath(MySerializableXact))
/* Check if someone else has already decided that we need to die */
if (SxactIsDoomed(MySerializableXact))
{
LWLockRelease(SerializableXactHashLock);
ereport(ERROR,
@ -4513,8 +4511,7 @@ PreCommit_CheckForSerializationFailure(void)
while (nearConflict)
{
if (!SxactIsCommitted(nearConflict->sxactOut)
&& !SxactIsRolledBack(nearConflict->sxactOut)
&& !SxactIsMarkedForDeath(nearConflict->sxactOut))
&& !SxactIsDoomed(nearConflict->sxactOut))
{
RWConflict farConflict;
@ -4527,10 +4524,9 @@ PreCommit_CheckForSerializationFailure(void)
if (farConflict->sxactOut == MySerializableXact
|| (!SxactIsCommitted(farConflict->sxactOut)
&& !SxactIsReadOnly(farConflict->sxactOut)
&& !SxactIsRolledBack(farConflict->sxactOut)
&& !SxactIsMarkedForDeath(farConflict->sxactOut)))
&& !SxactIsDoomed(farConflict->sxactOut)))
{
nearConflict->sxactOut->flags |= SXACT_FLAG_MARKED_FOR_DEATH;
nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
break;
}
farConflict = (RWConflict)

View File

@ -90,22 +90,21 @@ typedef struct SERIALIZABLEXACT
int pid; /* pid of associated process */
} SERIALIZABLEXACT;
#define SXACT_FLAG_ROLLED_BACK 0x00000001
#define SXACT_FLAG_COMMITTED 0x00000002
#define SXACT_FLAG_COMMITTED 0x00000001 /* already committed */
#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
* conflict out *to a transaction which committed ahead of it*. It's hard
* to get that into a name of a reasonable length.
*/
#define SXACT_FLAG_CONFLICT_OUT 0x00000004
#define SXACT_FLAG_READ_ONLY 0x00000008
#define SXACT_FLAG_MARKED_FOR_DEATH 0x00000010
#define SXACT_FLAG_CONFLICT_OUT 0x00000008
#define SXACT_FLAG_READ_ONLY 0x00000010
#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000020
#define SXACT_FLAG_RO_SAFE 0x00000040
#define SXACT_FLAG_RO_UNSAFE 0x00000080
#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000100
#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