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

Commitcb2d158

Browse files
committed
Fix locking while setting flags in MySerializableXact.
Even if a flag is modified only by the backend owning the transaction, it'snot safe to modify it without a lock. Another backend might be setting orclearing a different flag in the flags field concurrently, and thatoperation might be lost because setting or clearing a bit in a word is notatomic.Make did-write flag a simple backend-private boolean variable, because itwas only set or tested in the owning backend (except when committing aprepared transaction, but it's not worthwhile to optimize for the case of aread-only prepared transaction). This also eliminates the need to addlocking where that flag is set.Also, set the did-write flag when doing DDL operations like DROP TABLE orTRUNCATE -- that was missed earlier.
1 parentd69149e commitcb2d158

File tree

2 files changed

+61
-39
lines changed

2 files changed

+61
-39
lines changed

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

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -392,10 +392,11 @@ static HTAB *LocalPredicateLockHash = NULL;
392392

393393
/*
394394
* Keep a pointer to the currently-running serializable transaction (if any)
395-
* for quick reference.
396-
*TODO SSI: Remove volatile qualifier and the then-unnecessary casts?
395+
* for quick reference. Also, remember if we have written anything that could
396+
*cause a rw-conflict.
397397
*/
398-
staticvolatileSERIALIZABLEXACT*MySerializableXact=InvalidSerializableXact;
398+
staticSERIALIZABLEXACT*MySerializableXact=InvalidSerializableXact;
399+
staticboolMyXactDidWrite= false;
399400

400401
/* local functions */
401402

@@ -1424,20 +1425,30 @@ GetSafeSnapshot(Snapshot origSnapshot)
14241425
if (MySerializableXact==InvalidSerializableXact)
14251426
returnsnapshot;/* no concurrent r/w xacts; it's safe */
14261427

1427-
MySerializableXact->flags |=SXACT_FLAG_DEFERRABLE_WAITING;
1428+
LWLockAcquire(SerializableXactHashLock,LW_EXCLUSIVE);
14281429

14291430
/*
14301431
* Wait for concurrent transactions to finish. Stop early if one of
14311432
* them marked us as conflicted.
14321433
*/
1434+
MySerializableXact->flags |=SXACT_FLAG_DEFERRABLE_WAITING;
14331435
while (!(SHMQueueEmpty((SHM_QUEUE*)
14341436
&MySerializableXact->possibleUnsafeConflicts)||
14351437
SxactIsROUnsafe(MySerializableXact)))
1438+
{
1439+
LWLockRelease(SerializableXactHashLock);
14361440
ProcWaitForSignal();
1437-
1441+
LWLockAcquire(SerializableXactHashLock,LW_EXCLUSIVE);
1442+
}
14381443
MySerializableXact->flags &= ~SXACT_FLAG_DEFERRABLE_WAITING;
1444+
14391445
if (!SxactIsROUnsafe(MySerializableXact))
1446+
{
1447+
LWLockRelease(SerializableXactHashLock);
14401448
break;/* success */
1449+
}
1450+
1451+
LWLockRelease(SerializableXactHashLock);
14411452

14421453
/* else, need to retry... */
14431454
ereport(DEBUG2,
@@ -1600,6 +1611,7 @@ RegisterSerializableTransactionInt(Snapshot snapshot)
16001611
}
16011612

16021613
MySerializableXact=sxact;
1614+
MyXactDidWrite= false;/* haven't written anything yet */
16031615

16041616
LWLockRelease(SerializableXactHashLock);
16051617

@@ -1635,24 +1647,24 @@ RegisterPredicateLockingXid(const TransactionId xid)
16351647
if (MySerializableXact==InvalidSerializableXact)
16361648
return;
16371649

1638-
/* This should only be done once per transaction. */
1639-
Assert(MySerializableXact->topXid==InvalidTransactionId);
1640-
16411650
/* We should have a valid XID and be at the top level. */
16421651
Assert(TransactionIdIsValid(xid));
16431652

1653+
LWLockAcquire(SerializableXactHashLock,LW_EXCLUSIVE);
1654+
1655+
/* This should only be done once per transaction. */
1656+
Assert(MySerializableXact->topXid==InvalidTransactionId);
1657+
16441658
MySerializableXact->topXid=xid;
16451659

16461660
sxidtag.xid=xid;
1647-
LWLockAcquire(SerializableXactHashLock,LW_EXCLUSIVE);
16481661
sxid= (SERIALIZABLEXID*)hash_search(SerializableXidHash,
16491662
&sxidtag,
16501663
HASH_ENTER,&found);
1651-
Assert(sxid!=NULL);
16521664
Assert(!found);
16531665

16541666
/* Initialize the structure. */
1655-
sxid->myXact=(SERIALIZABLEXACT*)MySerializableXact;
1667+
sxid->myXact=MySerializableXact;
16561668
LWLockRelease(SerializableXactHashLock);
16571669
}
16581670

@@ -1881,7 +1893,7 @@ DeleteChildTargetLocks(const PREDICATELOCKTARGETTAG *newtargettag)
18811893
PREDICATELOCK*predlock;
18821894

18831895
LWLockAcquire(SerializablePredicateLockListLock,LW_SHARED);
1884-
sxact=(SERIALIZABLEXACT*)MySerializableXact;
1896+
sxact=MySerializableXact;
18851897
predlock= (PREDICATELOCK*)
18861898
SHMQueueNext(&(sxact->predicateLocks),
18871899
&(sxact->predicateLocks),
@@ -2200,8 +2212,7 @@ PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
22002212
locallock->childLocks=0;
22012213

22022214
/* Actually create the lock */
2203-
CreatePredicateLock(targettag,targettaghash,
2204-
(SERIALIZABLEXACT*)MySerializableXact);
2215+
CreatePredicateLock(targettag,targettaghash,MySerializableXact);
22052216

22062217
/*
22072218
* Lock has been acquired. Check whether it should be promoted to a
@@ -3042,7 +3053,7 @@ ReleasePredicateLocks(const bool isCommit)
30423053
Assert(IsolationIsSerializable());
30433054

30443055
/* We'd better not already be on the cleanup list. */
3045-
Assert(!SxactIsOnFinishedList((SERIALIZABLEXACT*)MySerializableXact));
3056+
Assert(!SxactIsOnFinishedList(MySerializableXact));
30463057

30473058
topLevelIsDeclaredReadOnly=SxactIsReadOnly(MySerializableXact);
30483059

@@ -3070,7 +3081,7 @@ ReleasePredicateLocks(const bool isCommit)
30703081
MySerializableXact->flags |=SXACT_FLAG_COMMITTED;
30713082
MySerializableXact->commitSeqNo=++(PredXact->LastSxactCommitSeqNo);
30723083
/* Recognize implicit read-only transaction (commit without write). */
3073-
if (!(MySerializableXact->flags&SXACT_FLAG_DID_WRITE))
3084+
if (!MyXactDidWrite)
30743085
MySerializableXact->flags |=SXACT_FLAG_READ_ONLY;
30753086
}
30763087
else
@@ -3218,7 +3229,7 @@ ReleasePredicateLocks(const bool isCommit)
32183229

32193230
/* Mark conflicted if necessary. */
32203231
if (isCommit
3221-
&&(MySerializableXact->flags&SXACT_FLAG_DID_WRITE)
3232+
&&MyXactDidWrite
32223233
&&SxactHasConflictOut(MySerializableXact)
32233234
&& (MySerializableXact->SeqNo.earliestOutConflictCommit
32243235
<=roXact->SeqNo.lastCommitBeforeSnapshot))
@@ -3282,15 +3293,15 @@ ReleasePredicateLocks(const bool isCommit)
32823293
(SHM_QUEUE*)&(MySerializableXact->finishedLink));
32833294

32843295
if (!isCommit)
3285-
ReleaseOneSerializableXact((SERIALIZABLEXACT*)MySerializableXact,
3286-
false, false);
3296+
ReleaseOneSerializableXact(MySerializableXact, false, false);
32873297

32883298
LWLockRelease(SerializableFinishedListLock);
32893299

32903300
if (needToClear)
32913301
ClearOldPredicateLocks();
32923302

32933303
MySerializableXact=InvalidSerializableXact;
3304+
MyXactDidWrite= false;
32943305

32953306
/* Delete per-transaction lock table */
32963307
if (LocalPredicateLockHash!=NULL)
@@ -3851,7 +3862,7 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
38513862
return;
38523863
}
38533864

3854-
if (RWConflictExists((SERIALIZABLEXACT*)MySerializableXact,sxact))
3865+
if (RWConflictExists(MySerializableXact,sxact))
38553866
{
38563867
/* We don't want duplicate conflict records in the list. */
38573868
LWLockRelease(SerializableXactHashLock);
@@ -3862,7 +3873,7 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
38623873
* Flag the conflict. But first, if this conflict creates a dangerous
38633874
* structure, ereport an error.
38643875
*/
3865-
FlagRWConflict((SERIALIZABLEXACT*)MySerializableXact,sxact);
3876+
FlagRWConflict(MySerializableXact,sxact);
38663877
LWLockRelease(SerializableXactHashLock);
38673878
}
38683879

@@ -3944,7 +3955,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
39443955
&& (!SxactIsCommitted(sxact)
39453956
||TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
39463957
sxact->finishedBefore))
3947-
&& !RWConflictExists(sxact, (SERIALIZABLEXACT*)MySerializableXact))
3958+
&& !RWConflictExists(sxact,MySerializableXact))
39483959
{
39493960
LWLockRelease(SerializableXactHashLock);
39503961
LWLockAcquire(SerializableXactHashLock,LW_EXCLUSIVE);
@@ -3957,10 +3968,9 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
39573968
&& (!SxactIsCommitted(sxact)
39583969
||TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
39593970
sxact->finishedBefore))
3960-
&& !RWConflictExists(sxact,
3961-
(SERIALIZABLEXACT*)MySerializableXact))
3971+
&& !RWConflictExists(sxact,MySerializableXact))
39623972
{
3963-
FlagRWConflict(sxact,(SERIALIZABLEXACT*)MySerializableXact);
3973+
FlagRWConflict(sxact,MySerializableXact);
39643974
}
39653975

39663976
LWLockRelease(SerializableXactHashLock);
@@ -4065,7 +4075,11 @@ CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple,
40654075
errdetail("Cancelled on identification as a pivot, during conflict in checking."),
40664076
errhint("The transaction might succeed if retried.")));
40674077

4068-
MySerializableXact->flags |=SXACT_FLAG_DID_WRITE;
4078+
/*
4079+
* We're doing a write which might cause rw-conflicts now or later.
4080+
* Memorize that fact.
4081+
*/
4082+
MyXactDidWrite= true;
40694083

40704084
/*
40714085
* It is important that we check for locks from the finest granularity to
@@ -4150,6 +4164,12 @@ CheckTableForSerializableConflictIn(const Relation relation)
41504164
if (SkipSerialization(relation))
41514165
return;
41524166

4167+
/*
4168+
* We're doing a write which might cause rw-conflicts now or later.
4169+
* Memorize that fact.
4170+
*/
4171+
MyXactDidWrite= true;
4172+
41534173
Assert(relation->rd_index==NULL);/* not an index relation */
41544174

41554175
dbId=relation->rd_node.dbNode;
@@ -4192,10 +4212,10 @@ CheckTableForSerializableConflictIn(const Relation relation)
41924212
offsetof(PREDICATELOCK,targetLink));
41934213

41944214
if (predlock->tag.myXact!=MySerializableXact
4195-
&& !RWConflictExists(predlock->tag.myXact,
4196-
(SERIALIZABLEXACT*)MySerializableXact))
4197-
FlagRWConflict(predlock->tag.myXact,
4198-
(SERIALIZABLEXACT*)MySerializableXact);
4215+
&& !RWConflictExists(predlock->tag.myXact,MySerializableXact))
4216+
{
4217+
FlagRWConflict(predlock->tag.myXact,MySerializableXact);
4218+
}
41994219

42004220
predlock=nextpredlock;
42014221
}
@@ -4506,7 +4526,7 @@ AtPrepare_PredicateLocks(void)
45064526
TwoPhasePredicateXactRecord*xactRecord;
45074527
TwoPhasePredicateLockRecord*lockRecord;
45084528

4509-
sxact=(SERIALIZABLEXACT*)MySerializableXact;
4529+
sxact=MySerializableXact;
45104530
xactRecord=&(record.data.xactRecord);
45114531
lockRecord=&(record.data.lockRecord);
45124532

@@ -4583,6 +4603,7 @@ PostPrepare_PredicateLocks(TransactionId xid)
45834603
LocalPredicateLockHash=NULL;
45844604

45854605
MySerializableXact=InvalidSerializableXact;
4606+
MyXactDidWrite= false;
45864607
}
45874608

45884609
/*
@@ -4609,6 +4630,8 @@ PredicateLockTwoPhaseFinish(TransactionId xid, bool isCommit)
46094630

46104631
/* Release its locks */
46114632
MySerializableXact=sxid->myXact;
4633+
MyXactDidWrite= true;/* conservatively assume that we wrote
4634+
* something */
46124635
ReleasePredicateLocks(isCommit);
46134636
}
46144637

‎src/include/storage/predicate_internals.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,13 @@ typedef struct SERIALIZABLEXACT
9999
*/
100100
#defineSXACT_FLAG_CONFLICT_OUT0x00000004
101101
#defineSXACT_FLAG_READ_ONLY0x00000008
102-
#defineSXACT_FLAG_DID_WRITE0x00000010
103-
#defineSXACT_FLAG_MARKED_FOR_DEATH0x00000020
104-
#defineSXACT_FLAG_DEFERRABLE_WAITING0x00000040
105-
#defineSXACT_FLAG_RO_SAFE0x00000080
106-
#defineSXACT_FLAG_RO_UNSAFE0x00000100
107-
#defineSXACT_FLAG_SUMMARY_CONFLICT_IN0x00000200
108-
#defineSXACT_FLAG_SUMMARY_CONFLICT_OUT0x00000400
109-
#defineSXACT_FLAG_PREPARED0x00000800
102+
#defineSXACT_FLAG_MARKED_FOR_DEATH0x00000010
103+
#defineSXACT_FLAG_DEFERRABLE_WAITING0x00000020
104+
#defineSXACT_FLAG_RO_SAFE0x00000040
105+
#defineSXACT_FLAG_RO_UNSAFE0x00000080
106+
#defineSXACT_FLAG_SUMMARY_CONFLICT_IN0x00000100
107+
#defineSXACT_FLAG_SUMMARY_CONFLICT_OUT0x00000200
108+
#defineSXACT_FLAG_PREPARED0x00000400
110109

111110
/*
112111
* The following types are used to provide an ad hoc list for holding

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp