postgres.git / summary / log / commit / refs

commit    7b745d85b80d4492c4df8d9769592c7aad1f63d2
Author:   Alvaro Herrera <alvherre@alvh.no-ip.org>
Date:     Tue Jan 30 17:11:17 2024 +0000
First released in: 17.0

    Split use of SerialSLRULock, creating SerialControlLock
    
    predicate.c has been using SerialSLRULock (the control lock for its SLRU
    structure) to coordinate access to SerialControlData, another of its
    numerous shared memory structures; this is unnecessary and confuses
    further SLRU scalability work.  Create a separate LWLock to cover
    SerialControlData.
    
    Extracted from a larger patch from the same author, and some additional
    changes by Álvaro.
    
    Author: Dilip Kumar <dilip.kumar@enterprisedb.com>
    Discussion: https://postgr.es/m/CAFiTN-vzDvNz=ExGXz6gdyjtzGixKSqs0mKHMmaQ8sOSEFZ33A@mail.gmail.com


src/backend/storage/lmgr/lwlocknames.txt | 1 + src/backend/storage/lmgr/predicate.c | 41 ++++++++++++++++++------- src/backend/utils/activity/wait_event_names.txt | 1 + 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt index a0163b21879..3d59d3646e5 100644 --- a/src/backend/storage/lmgr/lwlocknames.txt +++ b/src/backend/storage/lmgr/lwlocknames.txt @@ -57,3 +57,4 @@ WaitEventExtensionLock 48 WALSummarizerLock 49 DSMRegistryLock 50 InjectionPointLock 51 +SerialControlLock 52 diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index ee5ea1175c7..eed63a05ed8 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -134,6 +134,11 @@ * SerializableXactHashLock * - Protects both PredXact and SerializableXidHash. * + * SerialControlLock + * - Protects SerialControlData members + * + * SerialSLRULock + * - Protects SerialSlruCtl * * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California @@ -828,9 +833,11 @@ SerialInit(void) /* * Set control information to reflect empty SLRU. */ + LWLockAcquire(SerialControlLock, LW_EXCLUSIVE); serialControl->headPage = -1; serialControl->headXid = InvalidTransactionId; serialControl->tailXid = InvalidTransactionId; + LWLockRelease(SerialControlLock); } } @@ -852,7 +859,12 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo) targetPage = SerialPage(xid); - LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE); + /* + * In this routine, we must hold both SerialControlLock and SerialSLRULock + * simultaneously while making the SLRU data catch up with the new state + * that we determine. + */ + LWLockAcquire(SerialControlLock, LW_EXCLUSIVE); /* * If no serializable transactions are active, there shouldn't be anything @@ -886,6 +898,8 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo) if (isNewPage) serialControl->headPage = targetPage; + LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE); + if (isNewPage) { /* Initialize intervening pages. */ @@ -903,6 +917,7 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo) SerialSlruCtl->shared->page_dirty[slotno] = true; LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); } /* @@ -920,10 +935,10 @@ SerialGetMinConflictCommitSeqNo(TransactionId xid) Assert(TransactionIdIsValid(xid)); - LWLockAcquire(SerialSLRULock, LW_SHARED); + LWLockAcquire(SerialControlLock, LW_SHARED); headXid = serialControl->headXid; tailXid = serialControl->tailXid; - LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); if (!TransactionIdIsValid(headXid)) return 0; @@ -954,7 +969,7 @@ SerialGetMinConflictCommitSeqNo(TransactionId xid) static void SerialSetActiveSerXmin(TransactionId xid) { - LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE); + LWLockAcquire(SerialControlLock, LW_EXCLUSIVE); /* * When no sxacts are active, nothing overlaps, set the xid values to @@ -966,7 +981,7 @@ SerialSetActiveSerXmin(TransactionId xid) { serialControl->tailXid = InvalidTransactionId; serialControl->headXid = InvalidTransactionId; - LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); return; } @@ -984,7 +999,7 @@ SerialSetActiveSerXmin(TransactionId xid) { serialControl->tailXid = xid; } - LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); return; } @@ -993,7 +1008,7 @@ SerialSetActiveSerXmin(TransactionId xid) serialControl->tailXid = xid; - LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); } /* @@ -1007,12 +1022,12 @@ CheckPointPredicate(void) { int truncateCutoffPage; - LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE); + LWLockAcquire(SerialControlLock, LW_EXCLUSIVE); /* Exit quickly if the SLRU is currently not in use. */ if (serialControl->headPage < 0) { - LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); return; } @@ -1072,9 +1087,13 @@ CheckPointPredicate(void) serialControl->headPage = -1; } - LWLockRelease(SerialSLRULock); + LWLockRelease(SerialControlLock); - /* Truncate away pages that are no longer required */ + /* + * Truncate away pages that are no longer required. Note that no + * additional locking is required, because this is only called as part of + * a checkpoint, and the validity limits have already been determined. + */ SimpleLruTruncate(SerialSlruCtl, truncateCutoffPage); /* diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt index a5df835dd41..cd22dca7021 100644 --- a/src/backend/utils/activity/wait_event_names.txt +++ b/src/backend/utils/activity/wait_event_names.txt @@ -331,6 +331,7 @@ WaitEventExtension "Waiting to read or update custom wait events information for WALSummarizer "Waiting to read or update WAL summarization state." DSMRegistry "Waiting to read or update the dynamic shared memory registry." InjectionPoint "Waiting to read or update information related to injection points." +SerialControl "Waiting to read or update shared <filename>pg_serial</filename> state." # # END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE) [parent: 776621a5e479]