@@ -3638,6 +3638,8 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
36383638LWLockId partitionLock ;
36393639PREDICATELOCKTARGET * target ;
36403640PREDICATELOCK * predlock ;
3641+ PREDICATELOCK * mypredlock = NULL ;
3642+ PREDICATELOCKTAG mypredlocktag ;
36413643
36423644Assert (MySerializableXact != InvalidSerializableXact );
36433645
@@ -3683,139 +3685,21 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
36833685if (sxact == MySerializableXact )
36843686{
36853687/*
3686- * If we're getting a write lock onthe tuple and we're not in a
3687- *subtransaction, we don't need a predicate (SIREAD) lock. We
3688- *can't use this optimization within a subtransaction because the
3689- *subtransaction could be rolled back, and we would be left
3690- *without any lock at the top level .
3688+ * If we're getting a write lock ona tuple, we don't need
3689+ * a predicate (SIREAD) lock on the same tuple. We can
3690+ *safely remove our SIREAD lock, but we'll defer doing so
3691+ *until after the loop because that requires upgrading to
3692+ *an exclusive partition lock .
36913693 *
3692- * At this point our transaction already has an ExclusiveRowLock
3693- * on the relation, so we are OK to drop the predicate lock on the
3694- * tuple, if found, without fearing that another write against the
3695- * tuple will occur before the MVCC information makes it to the
3696- * buffer.
3694+ * We can't use this optimization within a subtransaction
3695+ * because the subtransaction could roll back, and we
3696+ * would be left without any lock at the top level.
36973697 */
36983698if (!IsSubTransaction ()
36993699&& GET_PREDICATELOCKTARGETTAG_OFFSET (* targettag ))
37003700{
3701- uint32 predlockhashcode ;
3702- PREDICATELOCKTARGET * rmtarget = NULL ;
3703- PREDICATELOCK * rmpredlock ;
3704- LOCALPREDICATELOCK * locallock ,
3705- * rmlocallock ;
3706-
3707- /*
3708- * This is a tuple on which we have a tuple predicate lock. We
3709- * only have shared LW locks now; release those, and get
3710- * exclusive locks only while we modify things.
3711- */
3712- LWLockRelease (SerializableXactHashLock );
3713- LWLockRelease (partitionLock );
3714- LWLockAcquire (SerializablePredicateLockListLock ,LW_SHARED );
3715- LWLockAcquire (partitionLock ,LW_EXCLUSIVE );
3716- LWLockAcquire (SerializableXactHashLock ,LW_EXCLUSIVE );
3717-
3718- /*
3719- * Remove the predicate lock from shared memory, if it wasn't
3720- * removed while the locks were released. One way that could
3721- * happen is from autovacuum cleaning up an index.
3722- */
3723- predlockhashcode = PredicateLockHashCodeFromTargetHashCode
3724- (& (predlock -> tag ),targettaghash );
3725- rmpredlock = (PREDICATELOCK * )
3726- hash_search_with_hash_value (PredicateLockHash ,
3727- & (predlock -> tag ),
3728- predlockhashcode ,
3729- HASH_FIND ,NULL );
3730- if (rmpredlock )
3731- {
3732- Assert (rmpredlock == predlock );
3733-
3734- SHMQueueDelete (predlocktargetlink );
3735- SHMQueueDelete (& (predlock -> xactLink ));
3736-
3737- rmpredlock = (PREDICATELOCK * )
3738- hash_search_with_hash_value (PredicateLockHash ,
3739- & (predlock -> tag ),
3740- predlockhashcode ,
3741- HASH_REMOVE ,NULL );
3742- Assert (rmpredlock == predlock );
3743-
3744- RemoveTargetIfNoLongerUsed (target ,targettaghash );
3745-
3746- LWLockRelease (SerializableXactHashLock );
3747- LWLockRelease (partitionLock );
3748- LWLockRelease (SerializablePredicateLockListLock );
3749-
3750- locallock = (LOCALPREDICATELOCK * )
3751- hash_search_with_hash_value (LocalPredicateLockHash ,
3752- targettag ,targettaghash ,
3753- HASH_FIND ,NULL );
3754-
3755- /*
3756- * Remove entry in local lock table if it exists and has
3757- * no children. It's OK if it doesn't exist; that means
3758- * the lock was transferred to a new target by a different
3759- * backend.
3760- */
3761- if (locallock != NULL )
3762- {
3763- locallock -> held = false;
3764-
3765- if (locallock -> childLocks == 0 )
3766- {
3767- rmlocallock = (LOCALPREDICATELOCK * )
3768- hash_search_with_hash_value (LocalPredicateLockHash ,
3769- targettag ,targettaghash ,
3770- HASH_REMOVE ,NULL );
3771- Assert (rmlocallock == locallock );
3772- }
3773- }
3774-
3775- DecrementParentLocks (targettag );
3776-
3777- /*
3778- * If we've cleaned up the last of the predicate locks for
3779- * the target, bail out before re-acquiring the locks.
3780- */
3781- if (rmtarget )
3782- return ;
3783-
3784- /*
3785- * The list has been altered. Start over at the front.
3786- */
3787- LWLockAcquire (partitionLock ,LW_SHARED );
3788- nextpredlock = (PREDICATELOCK * )
3789- SHMQueueNext (& (target -> predicateLocks ),
3790- & (target -> predicateLocks ),
3791- offsetof(PREDICATELOCK ,targetLink ));
3792-
3793- LWLockAcquire (SerializableXactHashLock ,LW_SHARED );
3794- }
3795- else
3796- {
3797- /*
3798- * The predicate lock was cleared while we were attempting
3799- * to upgrade our lightweight locks. Revert to the shared
3800- * locks.
3801- */
3802- LWLockRelease (SerializableXactHashLock );
3803- LWLockRelease (partitionLock );
3804- LWLockRelease (SerializablePredicateLockListLock );
3805- LWLockAcquire (partitionLock ,LW_SHARED );
3806-
3807- /*
3808- * The list may have been altered by another process while
3809- * we weren't holding the partition lock. Start over at
3810- * the front.
3811- */
3812- nextpredlock = (PREDICATELOCK * )
3813- SHMQueueNext (& (target -> predicateLocks ),
3814- & (target -> predicateLocks ),
3815- offsetof(PREDICATELOCK ,targetLink ));
3816-
3817- LWLockAcquire (SerializableXactHashLock ,LW_SHARED );
3818- }
3701+ mypredlock = predlock ;
3702+ mypredlocktag = predlock -> tag ;
38193703}
38203704}
38213705else if (!SxactIsRolledBack (sxact )
@@ -3849,6 +3733,73 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
38493733}
38503734LWLockRelease (SerializableXactHashLock );
38513735LWLockRelease (partitionLock );
3736+
3737+ /*
3738+ * If we found one of our own SIREAD locks to remove, remove it
3739+ * now.
3740+ *
3741+ * At this point our transaction already has an ExclusiveRowLock
3742+ * on the relation, so we are OK to drop the predicate lock on the
3743+ * tuple, if found, without fearing that another write against the
3744+ * tuple will occur before the MVCC information makes it to the
3745+ * buffer.
3746+ */
3747+ if (mypredlock != NULL )
3748+ {
3749+ uint32 predlockhashcode ;
3750+ PREDICATELOCK * rmpredlock ;
3751+
3752+ LWLockAcquire (SerializablePredicateLockListLock ,LW_SHARED );
3753+ LWLockAcquire (partitionLock ,LW_EXCLUSIVE );
3754+ LWLockAcquire (SerializableXactHashLock ,LW_EXCLUSIVE );
3755+
3756+ /*
3757+ * Remove the predicate lock from shared memory, if it wasn't
3758+ * removed while the locks were released. One way that could
3759+ * happen is from autovacuum cleaning up an index.
3760+ */
3761+ predlockhashcode = PredicateLockHashCodeFromTargetHashCode
3762+ (& mypredlocktag ,targettaghash );
3763+ rmpredlock = (PREDICATELOCK * )
3764+ hash_search_with_hash_value (PredicateLockHash ,
3765+ & mypredlocktag ,
3766+ predlockhashcode ,
3767+ HASH_FIND ,NULL );
3768+ if (rmpredlock != NULL )
3769+ {
3770+ Assert (rmpredlock == mypredlock );
3771+
3772+ SHMQueueDelete (& (mypredlock -> targetLink ));
3773+ SHMQueueDelete (& (mypredlock -> xactLink ));
3774+
3775+ rmpredlock = (PREDICATELOCK * )
3776+ hash_search_with_hash_value (PredicateLockHash ,
3777+ & mypredlocktag ,
3778+ predlockhashcode ,
3779+ HASH_REMOVE ,NULL );
3780+ Assert (rmpredlock == mypredlock );
3781+
3782+ RemoveTargetIfNoLongerUsed (target ,targettaghash );
3783+ }
3784+
3785+ LWLockRelease (SerializableXactHashLock );
3786+ LWLockRelease (partitionLock );
3787+ LWLockRelease (SerializablePredicateLockListLock );
3788+
3789+ if (rmpredlock != NULL )
3790+ {
3791+ /*
3792+ * Remove entry in local lock table if it exists. It's OK
3793+ * if it doesn't exist; that means the lock was
3794+ * transferred to a new target by a different backend.
3795+ */
3796+ hash_search_with_hash_value (LocalPredicateLockHash ,
3797+ targettag ,targettaghash ,
3798+ HASH_REMOVE ,NULL );
3799+
3800+ DecrementParentLocks (targettag );
3801+ }
3802+ }
38523803}
38533804
38543805/*