From fbc0d07796bcae8b2ee4b09ed236877338c95130 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 8 Apr 2011 15:29:02 -0400 Subject: [PATCH] Partially roll back overenthusiastic SSI optimization. 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 | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 46b86546ee..11dede9e70 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -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;