mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Use an LWLock instead of a spinlock in waitlsn.c
This should prevent busy-waiting when number of waiting processes is high. Discussion: https://postgr.es/m/202404030658.hhj3vfxeyhft%40alvherre.pgsql Author: Alvaro Herrera
This commit is contained in:
parent
1577081e96
commit
25f42429e2
@ -58,7 +58,6 @@ WaitLSNShmemInit(void)
|
|||||||
&found);
|
&found);
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
SpinLockInit(&waitLSN->waitersHeapMutex);
|
|
||||||
pg_atomic_init_u64(&waitLSN->minWaitedLSN, PG_UINT64_MAX);
|
pg_atomic_init_u64(&waitLSN->minWaitedLSN, PG_UINT64_MAX);
|
||||||
pairingheap_initialize(&waitLSN->waitersHeap, lsn_cmp, NULL);
|
pairingheap_initialize(&waitLSN->waitersHeap, lsn_cmp, NULL);
|
||||||
memset(&waitLSN->procInfos, 0, MaxBackends * sizeof(WaitLSNProcInfo));
|
memset(&waitLSN->procInfos, 0, MaxBackends * sizeof(WaitLSNProcInfo));
|
||||||
@ -115,13 +114,13 @@ addLSNWaiter(XLogRecPtr lsn)
|
|||||||
procInfo->procnum = MyProcNumber;
|
procInfo->procnum = MyProcNumber;
|
||||||
procInfo->waitLSN = lsn;
|
procInfo->waitLSN = lsn;
|
||||||
|
|
||||||
SpinLockAcquire(&waitLSN->waitersHeapMutex);
|
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
pairingheap_add(&waitLSN->waitersHeap, &procInfo->phNode);
|
pairingheap_add(&waitLSN->waitersHeap, &procInfo->phNode);
|
||||||
procInfo->inHeap = true;
|
procInfo->inHeap = true;
|
||||||
updateMinWaitedLSN();
|
updateMinWaitedLSN();
|
||||||
|
|
||||||
SpinLockRelease(&waitLSN->waitersHeapMutex);
|
LWLockRelease(WaitLSNLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -132,11 +131,11 @@ deleteLSNWaiter(void)
|
|||||||
{
|
{
|
||||||
WaitLSNProcInfo *procInfo = &waitLSN->procInfos[MyProcNumber];
|
WaitLSNProcInfo *procInfo = &waitLSN->procInfos[MyProcNumber];
|
||||||
|
|
||||||
SpinLockAcquire(&waitLSN->waitersHeapMutex);
|
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
if (!procInfo->inHeap)
|
if (!procInfo->inHeap)
|
||||||
{
|
{
|
||||||
SpinLockRelease(&waitLSN->waitersHeapMutex);
|
LWLockRelease(WaitLSNLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +143,7 @@ deleteLSNWaiter(void)
|
|||||||
procInfo->inHeap = false;
|
procInfo->inHeap = false;
|
||||||
updateMinWaitedLSN();
|
updateMinWaitedLSN();
|
||||||
|
|
||||||
SpinLockRelease(&waitLSN->waitersHeapMutex);
|
LWLockRelease(WaitLSNLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -160,7 +159,7 @@ WaitLSNSetLatches(XLogRecPtr currentLSN)
|
|||||||
|
|
||||||
wakeUpProcNums = palloc(sizeof(int) * MaxBackends);
|
wakeUpProcNums = palloc(sizeof(int) * MaxBackends);
|
||||||
|
|
||||||
SpinLockAcquire(&waitLSN->waitersHeapMutex);
|
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate the pairing heap of waiting processes till we find LSN not yet
|
* Iterate the pairing heap of waiting processes till we find LSN not yet
|
||||||
@ -182,7 +181,7 @@ WaitLSNSetLatches(XLogRecPtr currentLSN)
|
|||||||
|
|
||||||
updateMinWaitedLSN();
|
updateMinWaitedLSN();
|
||||||
|
|
||||||
SpinLockRelease(&waitLSN->waitersHeapMutex);
|
LWLockRelease(WaitLSNLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set latches for processes, whose waited LSNs are already replayed. This
|
* Set latches for processes, whose waited LSNs are already replayed. This
|
||||||
|
@ -345,6 +345,7 @@ 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."
|
SerialControl "Waiting to read or update shared <filename>pg_serial</filename> state."
|
||||||
|
WaitLSN "Waiting to read or update shared Wait-for-LSN state."
|
||||||
|
|
||||||
#
|
#
|
||||||
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
|
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
|
||||||
|
@ -55,13 +55,10 @@ typedef struct WaitLSNState
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* A pairing heap of waiting processes order by LSN values (least LSN is
|
* A pairing heap of waiting processes order by LSN values (least LSN is
|
||||||
* on top).
|
* on top). Protected by WaitLSNLock.
|
||||||
*/
|
*/
|
||||||
pairingheap waitersHeap;
|
pairingheap waitersHeap;
|
||||||
|
|
||||||
/* A mutex protecting the pairing heap above */
|
|
||||||
slock_t waitersHeapMutex;
|
|
||||||
|
|
||||||
/* An array with per-process information, indexed by the process number */
|
/* An array with per-process information, indexed by the process number */
|
||||||
WaitLSNProcInfo procInfos[FLEXIBLE_ARRAY_MEMBER];
|
WaitLSNProcInfo procInfos[FLEXIBLE_ARRAY_MEMBER];
|
||||||
} WaitLSNState;
|
} WaitLSNState;
|
||||||
|
@ -83,3 +83,4 @@ PG_LWLOCK(49, WALSummarizer)
|
|||||||
PG_LWLOCK(50, DSMRegistry)
|
PG_LWLOCK(50, DSMRegistry)
|
||||||
PG_LWLOCK(51, InjectionPoint)
|
PG_LWLOCK(51, InjectionPoint)
|
||||||
PG_LWLOCK(52, SerialControl)
|
PG_LWLOCK(52, SerialControl)
|
||||||
|
PG_LWLOCK(53, WaitLSN)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user