Fix bug introduced by recent SSI to merge ROLLED_BACK and
authorHeikki Linnakangas <[email protected]>
Tue, 21 Jun 2011 11:12:40 +0000 (14:12 +0300)
committerHeikki Linnakangas <[email protected]>
Tue, 21 Jun 2011 11:49:50 +0000 (14:49 +0300)
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

src/backend/storage/lmgr/predicate.c
src/include/storage/predicate_internals.h

index 3678878f03ede4a06dffcd72952d4e489584888e..8cbca78fb76565e7f9aa9cd58d7433af3429db13 100644 (file)
 
 #define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
 #define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
+#define SxactIsRolledBack(sxact) (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 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)
@@ -3046,7 +3047,7 @@ SetNewSxactGlobalXmin(void)
 
    for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
    {
-       if (!SxactIsDoomed(sxact)
+       if (!SxactIsRolledBack(sxact)
            && !SxactIsCommitted(sxact)
            && sxact != OldCommittedSxact)
        {
@@ -3113,6 +3114,7 @@ ReleasePredicateLocks(const bool isCommit)
    Assert(!isCommit || SxactIsPrepared(MySerializableXact));
    Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
    Assert(!SxactIsCommitted(MySerializableXact));
+   Assert(!SxactIsRolledBack(MySerializableXact));
 
    /* may not be serializable during COMMIT/ROLLBACK PREPARED */
    if (MySerializableXact->pid != 0)
@@ -3151,7 +3153,22 @@ ReleasePredicateLocks(const bool isCommit)
            MySerializableXact->flags |= SXACT_FLAG_READ_ONLY;
    }
    else
+   {
+       /*
+        * The DOOMED flag indicates that we intend to roll back this
+        * transaction and so it should not cause serialization failures for
+        * other transactions that conflict with it. Note that this flag might
+        * already be set, if another backend marked this transaction for
+        * abort.
+        *
+        * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
+        * has been called, and so the SerializableXact is eligible for
+        * cleanup. This means it should not be considered when calculating
+        * SxactGlobalXmin.
+        */
        MySerializableXact->flags |= SXACT_FLAG_DOOMED;
+       MySerializableXact->flags |= SXACT_FLAG_ROLLED_BACK;
+   }
 
    if (!topLevelIsDeclaredReadOnly)
    {
@@ -3527,7 +3544,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
                nextConflict;
 
    Assert(sxact != NULL);
-   Assert(SxactIsDoomed(sxact) || SxactIsCommitted(sxact));
+   Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact));
    Assert(LWLockHeldByMe(SerializableFinishedListLock));
 
    /*
index 495983f345805134d185d022ec84c69df78451ad..0c90f275d659734ce20e9f13296e695916c2a56c 100644 (file)
@@ -90,21 +90,22 @@ typedef struct SERIALIZABLEXACT
    int         pid;            /* pid of associated process */
 } SERIALIZABLEXACT;
 
-#define SXACT_FLAG_COMMITTED               0x00000001  /* already committed */
-#define SXACT_FLAG_PREPARED                    0x00000002  /* about to commit */
-#define SXACT_FLAG_DOOMED                  0x00000004  /* will roll back */
+#define SXACT_FLAG_COMMITTED           0x00000001      /* already committed */
+#define SXACT_FLAG_PREPARED                0x00000002      /* about to commit */
+#define SXACT_FLAG_ROLLED_BACK         0x00000004      /* already rolled back */
+#define SXACT_FLAG_DOOMED              0x00000008      /* 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                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_CONFLICT_OUT            0x00000010
+#define SXACT_FLAG_READ_ONLY           0x00000020
+#define SXACT_FLAG_DEFERRABLE_WAITING  0x00000040
+#define SXACT_FLAG_RO_SAFE             0x00000080
+#define SXACT_FLAG_RO_UNSAFE           0x00000100
+#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000200
+#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000400
 
 /*
  * The following types are used to provide an ad hoc list for holding