Skip to content

Commit 7cb2ff9

Browse files
committed
Fix bug introduced by recent SSI patch to merge ROLLED_BACK and
MARKED_FOR_DEATH flags into one. We still need the ROLLED_BACK flag to mark transactions that are in the process of being rolled back. To be precise, ROLLED_BACK now means that a transaction has already been discounted from the count of transactions with the oldest xmin, but not yet removed from the list of active transactions. Dan Ports
1 parent 31e8ab4 commit 7cb2ff9

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

src/backend/storage/lmgr/predicate.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@
246246

247247
#define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
248248
#define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
249+
#define SxactIsRolledBack(sxact) (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 0)
249250
#define SxactIsDoomed(sxact) (((sxact)->flags & SXACT_FLAG_DOOMED) != 0)
250251
#define SxactIsReadOnly(sxact) (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0)
251252
#define SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
@@ -3046,7 +3047,7 @@ SetNewSxactGlobalXmin(void)
30463047

30473048
for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
30483049
{
3049-
if (!SxactIsDoomed(sxact)
3050+
if (!SxactIsRolledBack(sxact)
30503051
&& !SxactIsCommitted(sxact)
30513052
&& sxact != OldCommittedSxact)
30523053
{
@@ -3113,6 +3114,7 @@ ReleasePredicateLocks(const bool isCommit)
31133114
Assert(!isCommit || SxactIsPrepared(MySerializableXact));
31143115
Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
31153116
Assert(!SxactIsCommitted(MySerializableXact));
3117+
Assert(!SxactIsRolledBack(MySerializableXact));
31163118

31173119
/* may not be serializable during COMMIT/ROLLBACK PREPARED */
31183120
if (MySerializableXact->pid != 0)
@@ -3151,7 +3153,22 @@ ReleasePredicateLocks(const bool isCommit)
31513153
MySerializableXact->flags |= SXACT_FLAG_READ_ONLY;
31523154
}
31533155
else
3156+
{
3157+
/*
3158+
* The DOOMED flag indicates that we intend to roll back this
3159+
* transaction and so it should not cause serialization failures for
3160+
* other transactions that conflict with it. Note that this flag might
3161+
* already be set, if another backend marked this transaction for
3162+
* abort.
3163+
*
3164+
* The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3165+
* has been called, and so the SerializableXact is eligible for
3166+
* cleanup. This means it should not be considered when calculating
3167+
* SxactGlobalXmin.
3168+
*/
31543169
MySerializableXact->flags |= SXACT_FLAG_DOOMED;
3170+
MySerializableXact->flags |= SXACT_FLAG_ROLLED_BACK;
3171+
}
31553172

31563173
if (!topLevelIsDeclaredReadOnly)
31573174
{
@@ -3527,7 +3544,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
35273544
nextConflict;
35283545

35293546
Assert(sxact != NULL);
3530-
Assert(SxactIsDoomed(sxact) || SxactIsCommitted(sxact));
3547+
Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact));
35313548
Assert(LWLockHeldByMe(SerializableFinishedListLock));
35323549

35333550
/*

src/include/storage/predicate_internals.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,21 +90,22 @@ typedef struct SERIALIZABLEXACT
9090
int pid; /* pid of associated process */
9191
} SERIALIZABLEXACT;
9292

93-
#define SXACT_FLAG_COMMITTED 0x00000001 /* already committed */
94-
#define SXACT_FLAG_PREPARED 0x00000002 /* about to commit */
95-
#define SXACT_FLAG_DOOMED 0x00000004 /* will roll back */
93+
#define SXACT_FLAG_COMMITTED 0x00000001 /* already committed */
94+
#define SXACT_FLAG_PREPARED 0x00000002 /* about to commit */
95+
#define SXACT_FLAG_ROLLED_BACK 0x00000004 /* already rolled back */
96+
#define SXACT_FLAG_DOOMED 0x00000008 /* will roll back */
9697
/*
9798
* The following flag actually means that the flagged transaction has a
9899
* conflict out *to a transaction which committed ahead of it*. It's hard
99100
* to get that into a name of a reasonable length.
100101
*/
101-
#define SXACT_FLAG_CONFLICT_OUT 0x00000008
102-
#define SXACT_FLAG_READ_ONLY 0x00000010
103-
#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000020
104-
#define SXACT_FLAG_RO_SAFE 0x00000040
105-
#define SXACT_FLAG_RO_UNSAFE 0x00000080
106-
#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000100
107-
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000200
102+
#define SXACT_FLAG_CONFLICT_OUT 0x00000010
103+
#define SXACT_FLAG_READ_ONLY 0x00000020
104+
#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000040
105+
#define SXACT_FLAG_RO_SAFE 0x00000080
106+
#define SXACT_FLAG_RO_UNSAFE 0x00000100
107+
#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000200
108+
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000400
108109

109110
/*
110111
* The following types are used to provide an ad hoc list for holding

0 commit comments

Comments
 (0)