OSDN Git Service

Fix bug introduced by recent SSI patch to merge ROLLED_BACK and
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 21 Jun 2011 11:12:40 +0000 (14:12 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
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 3678878..8cbca78 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 495983f..0c90f27 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