Partially roll back overenthusiastic SSI optimization.
authorRobert Haas
Fri, 8 Apr 2011 19:29:02 +0000 (15:29 -0400)
committerRobert Haas
Fri, 8 Apr 2011 19:29:02 +0000 (15:29 -0400)
When a regular lock is held, SSI can use that in lieu of a predicate lock
to detect rw conflicts; but if the regular lock is being taken by a
subtransaction, we can't assume that it'll commit, so releasing the
parent transaction's lock in that case is a no-no.

Kevin Grittner

src/backend/storage/lmgr/predicate.c

index 46b86546ee074cda1b7cde47b2a79009fece1e50..11dede9e70b8805635a98f8def33ffd4caf89177 100644 (file)
@@ -3638,14 +3638,20 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
        if (sxact == MySerializableXact)
        {
            /*
-            * If we're getting a write lock on the tuple, we don't need a
-            * predicate (SIREAD) lock. At this point our transaction already
-            * has an ExclusiveRowLock on the relation, so we are OK to drop
-            * the predicate lock on the tuple, if found, without fearing that
-            * another write against the tuple will occur before the MVCC
-            * information makes it to the buffer.
+            * If we're getting a write lock on the tuple and we're not in a
+            * subtransaction, we don't need a predicate (SIREAD) lock.  We
+            * can't use this optimization within a subtransaction because
+            * the subtransaction could be rolled back, and we would be left
+            * without any lock at the top level.
+            * 
+            * At this point our transaction already has an ExclusiveRowLock
+            * on the relation, so we are OK to drop the predicate lock on
+            * the tuple, if found, without fearing that another write
+            * against the tuple will occur before the MVCC information
+            * makes it to the buffer.
             */
-           if (GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
+           if (!IsSubTransaction()
+               && GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
            {
                uint32      predlockhashcode;
                PREDICATELOCKTARGET *rmtarget = NULL;