Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 02f377d

Browse files
committed
Fix corner case in cleanup of transactions using SSI.
When the only remaining active transactions are READ ONLY, we do a "partial cleanup" of committed transactions because certain types of conflicts aren't possible anymore. For committed r/w transactions, we release the SIREAD locks but keep the SERIALIZABLEXACT. However, for committed r/o transactions, we can go further and release the SERIALIZABLEXACT too. The problem was with the latter case: we were returning the SERIALIZABLEXACT to the free list without removing it from the finished list. The only real change in the patch is the SHMQueueDelete line, but I also reworked some of the surrounding code to make it obvious that r/o and r/w transactions are handled differently -- the existing code felt a bit too clever. Dan Ports
1 parent ef007e6 commit 02f377d

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

src/backend/storage/lmgr/predicate.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3457,10 +3457,29 @@ ClearOldPredicateLocks(void)
34573457
else if (finishedSxact->commitSeqNo > PredXact->HavePartialClearedThrough
34583458
&& finishedSxact->commitSeqNo <= PredXact->CanPartialClearThrough)
34593459
{
3460+
/*
3461+
* Any active transactions that took their snapshot before this
3462+
* transaction committed are read-only, so we can clear part of
3463+
* its state.
3464+
*/
34603465
LWLockRelease(SerializableXactHashLock);
3461-
ReleaseOneSerializableXact(finishedSxact,
3462-
!SxactIsReadOnly(finishedSxact),
3463-
false);
3466+
3467+
if (SxactIsReadOnly(finishedSxact))
3468+
{
3469+
/* A read-only transaction can be removed entirely */
3470+
SHMQueueDelete(&(finishedSxact->finishedLink));
3471+
ReleaseOneSerializableXact(finishedSxact, false, false);
3472+
}
3473+
else
3474+
{
3475+
/*
3476+
* A read-write transaction can only be partially
3477+
* cleared. We need to keep the SERIALIZABLEXACT but
3478+
* can release the SIREAD locks and conflicts in.
3479+
*/
3480+
ReleaseOneSerializableXact(finishedSxact, true, false);
3481+
}
3482+
34643483
PredXact->HavePartialClearedThrough = finishedSxact->commitSeqNo;
34653484
LWLockAcquire(SerializableXactHashLock, LW_SHARED);
34663485
}
@@ -3566,6 +3585,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
35663585

35673586
Assert(sxact != NULL);
35683587
Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact));
3588+
Assert(partial || !SxactIsOnFinishedList(sxact));
35693589
Assert(LWLockHeldByMe(SerializableFinishedListLock));
35703590

35713591
/*

0 commit comments

Comments
 (0)