mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
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
This commit is contained in:
@ -57,3 +57,4 @@ WaitEventExtensionLock 48
|
|||||||
WALSummarizerLock 49
|
WALSummarizerLock 49
|
||||||
DSMRegistryLock 50
|
DSMRegistryLock 50
|
||||||
InjectionPointLock 51
|
InjectionPointLock 51
|
||||||
|
SerialControlLock 52
|
||||||
|
@ -134,6 +134,11 @@
|
|||||||
* SerializableXactHashLock
|
* SerializableXactHashLock
|
||||||
* - Protects both PredXact and SerializableXidHash.
|
* - Protects both PredXact and SerializableXidHash.
|
||||||
*
|
*
|
||||||
|
* SerialControlLock
|
||||||
|
* - Protects SerialControlData members
|
||||||
|
*
|
||||||
|
* SerialSLRULock
|
||||||
|
* - Protects SerialSlruCtl
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
@ -828,9 +833,11 @@ SerialInit(void)
|
|||||||
/*
|
/*
|
||||||
* Set control information to reflect empty SLRU.
|
* Set control information to reflect empty SLRU.
|
||||||
*/
|
*/
|
||||||
|
LWLockAcquire(SerialControlLock, LW_EXCLUSIVE);
|
||||||
serialControl->headPage = -1;
|
serialControl->headPage = -1;
|
||||||
serialControl->headXid = InvalidTransactionId;
|
serialControl->headXid = InvalidTransactionId;
|
||||||
serialControl->tailXid = InvalidTransactionId;
|
serialControl->tailXid = InvalidTransactionId;
|
||||||
|
LWLockRelease(SerialControlLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,7 +859,12 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
|
|||||||
|
|
||||||
targetPage = SerialPage(xid);
|
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
|
* If no serializable transactions are active, there shouldn't be anything
|
||||||
@ -886,6 +898,8 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
|
|||||||
if (isNewPage)
|
if (isNewPage)
|
||||||
serialControl->headPage = targetPage;
|
serialControl->headPage = targetPage;
|
||||||
|
|
||||||
|
LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
if (isNewPage)
|
if (isNewPage)
|
||||||
{
|
{
|
||||||
/* Initialize intervening pages. */
|
/* Initialize intervening pages. */
|
||||||
@ -903,6 +917,7 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
|
|||||||
SerialSlruCtl->shared->page_dirty[slotno] = true;
|
SerialSlruCtl->shared->page_dirty[slotno] = true;
|
||||||
|
|
||||||
LWLockRelease(SerialSLRULock);
|
LWLockRelease(SerialSLRULock);
|
||||||
|
LWLockRelease(SerialControlLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -920,10 +935,10 @@ SerialGetMinConflictCommitSeqNo(TransactionId xid)
|
|||||||
|
|
||||||
Assert(TransactionIdIsValid(xid));
|
Assert(TransactionIdIsValid(xid));
|
||||||
|
|
||||||
LWLockAcquire(SerialSLRULock, LW_SHARED);
|
LWLockAcquire(SerialControlLock, LW_SHARED);
|
||||||
headXid = serialControl->headXid;
|
headXid = serialControl->headXid;
|
||||||
tailXid = serialControl->tailXid;
|
tailXid = serialControl->tailXid;
|
||||||
LWLockRelease(SerialSLRULock);
|
LWLockRelease(SerialControlLock);
|
||||||
|
|
||||||
if (!TransactionIdIsValid(headXid))
|
if (!TransactionIdIsValid(headXid))
|
||||||
return 0;
|
return 0;
|
||||||
@ -954,7 +969,7 @@ SerialGetMinConflictCommitSeqNo(TransactionId xid)
|
|||||||
static void
|
static void
|
||||||
SerialSetActiveSerXmin(TransactionId xid)
|
SerialSetActiveSerXmin(TransactionId xid)
|
||||||
{
|
{
|
||||||
LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE);
|
LWLockAcquire(SerialControlLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When no sxacts are active, nothing overlaps, set the xid values to
|
* When no sxacts are active, nothing overlaps, set the xid values to
|
||||||
@ -966,7 +981,7 @@ SerialSetActiveSerXmin(TransactionId xid)
|
|||||||
{
|
{
|
||||||
serialControl->tailXid = InvalidTransactionId;
|
serialControl->tailXid = InvalidTransactionId;
|
||||||
serialControl->headXid = InvalidTransactionId;
|
serialControl->headXid = InvalidTransactionId;
|
||||||
LWLockRelease(SerialSLRULock);
|
LWLockRelease(SerialControlLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,7 +999,7 @@ SerialSetActiveSerXmin(TransactionId xid)
|
|||||||
{
|
{
|
||||||
serialControl->tailXid = xid;
|
serialControl->tailXid = xid;
|
||||||
}
|
}
|
||||||
LWLockRelease(SerialSLRULock);
|
LWLockRelease(SerialControlLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -993,7 +1008,7 @@ SerialSetActiveSerXmin(TransactionId xid)
|
|||||||
|
|
||||||
serialControl->tailXid = xid;
|
serialControl->tailXid = xid;
|
||||||
|
|
||||||
LWLockRelease(SerialSLRULock);
|
LWLockRelease(SerialControlLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1007,12 +1022,12 @@ CheckPointPredicate(void)
|
|||||||
{
|
{
|
||||||
int truncateCutoffPage;
|
int truncateCutoffPage;
|
||||||
|
|
||||||
LWLockAcquire(SerialSLRULock, LW_EXCLUSIVE);
|
LWLockAcquire(SerialControlLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
/* Exit quickly if the SLRU is currently not in use. */
|
/* Exit quickly if the SLRU is currently not in use. */
|
||||||
if (serialControl->headPage < 0)
|
if (serialControl->headPage < 0)
|
||||||
{
|
{
|
||||||
LWLockRelease(SerialSLRULock);
|
LWLockRelease(SerialControlLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,9 +1087,13 @@ CheckPointPredicate(void)
|
|||||||
serialControl->headPage = -1;
|
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);
|
SimpleLruTruncate(SerialSlruCtl, truncateCutoffPage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -331,6 +331,7 @@ WaitEventExtension "Waiting to read or update custom wait events information for
|
|||||||
WALSummarizer "Waiting to read or update WAL summarization state."
|
WALSummarizer "Waiting to read or update WAL summarization state."
|
||||||
DSMRegistry "Waiting to read or update the dynamic shared memory registry."
|
DSMRegistry "Waiting to read or update the dynamic shared memory registry."
|
||||||
InjectionPoint "Waiting to read or update information related to injection points."
|
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)
|
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
|
||||||
|
Reference in New Issue
Block a user