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

Skip to content

Commit 326b922

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 2106c55 commit 326b922

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
@@ -3528,10 +3528,29 @@ ClearOldPredicateLocks(void)
35283528
else if (finishedSxact->commitSeqNo > PredXact->HavePartialClearedThrough
35293529
&& finishedSxact->commitSeqNo <= PredXact->CanPartialClearThrough)
35303530
{
3531+
/*
3532+
* Any active transactions that took their snapshot before this
3533+
* transaction committed are read-only, so we can clear part of
3534+
* its state.
3535+
*/
35313536
LWLockRelease(SerializableXactHashLock);
3532-
ReleaseOneSerializableXact(finishedSxact,
3533-
!SxactIsReadOnly(finishedSxact),
3534-
false);
3537+
3538+
if (SxactIsReadOnly(finishedSxact))
3539+
{
3540+
/* A read-only transaction can be removed entirely */
3541+
SHMQueueDelete(&(finishedSxact->finishedLink));
3542+
ReleaseOneSerializableXact(finishedSxact, false, false);
3543+
}
3544+
else
3545+
{
3546+
/*
3547+
* A read-write transaction can only be partially
3548+
* cleared. We need to keep the SERIALIZABLEXACT but
3549+
* can release the SIREAD locks and conflicts in.
3550+
*/
3551+
ReleaseOneSerializableXact(finishedSxact, true, false);
3552+
}
3553+
35353554
PredXact->HavePartialClearedThrough = finishedSxact->commitSeqNo;
35363555
LWLockAcquire(SerializableXactHashLock, LW_SHARED);
35373556
}
@@ -3637,6 +3656,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
36373656

36383657
Assert(sxact != NULL);
36393658
Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact));
3659+
Assert(partial || !SxactIsOnFinishedList(sxact));
36403660
Assert(LWLockHeldByMe(SerializableFinishedListLock));
36413661

36423662
/*

0 commit comments

Comments
 (0)