Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit74aaa21

Browse files
committed
Fix race condition in CheckTargetForConflictsIn.
Dan Ports
1 parent6b449d9 commit74aaa21

File tree

1 file changed

+79
-128
lines changed

1 file changed

+79
-128
lines changed

‎src/backend/storage/lmgr/predicate.c

Lines changed: 79 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -3638,6 +3638,8 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
36383638
LWLockIdpartitionLock;
36393639
PREDICATELOCKTARGET*target;
36403640
PREDICATELOCK*predlock;
3641+
PREDICATELOCK*mypredlock=NULL;
3642+
PREDICATELOCKTAGmypredlocktag;
36413643

36423644
Assert(MySerializableXact!=InvalidSerializableXact);
36433645

@@ -3683,139 +3685,21 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
36833685
if (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 needa 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
*/
36983698
if (!IsSubTransaction()
36993699
&&GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
37003700
{
3701-
uint32predlockhashcode;
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
}
38213705
elseif (!SxactIsRolledBack(sxact)
@@ -3849,6 +3733,73 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
38493733
}
38503734
LWLockRelease(SerializableXactHashLock);
38513735
LWLockRelease(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+
uint32predlockhashcode;
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
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp