From 77bd5767bf041c5a99b3b509b7d8e65c4c43e58c Mon Sep 17 00:00:00 2001 From: alterego655 <824662526@qq.com> Date: Fri, 24 Jul 2026 16:34:29 +0800 Subject: [PATCH v4 3/5] Avoid locking when an LSN waiter is already removed WaitLSNWakeup() removes each selected waiter from its heap and clears its inHeap flag before setting its latch. When such a waiter later calls deleteLSNWaiter(), it acquires WaitLSNLock exclusively only to discover that there is nothing left to remove. Waking many waiters can therefore make them serialize on the lock for no useful work. Check inHeap before acquiring WaitLSNLock. A lockless false value is conclusive because only the owning backend can change inHeap from false to true. A concurrent waker can only clear it. A stale true value falls through to the existing recheck under the lock. --- src/backend/access/transam/xlogwait.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/access/transam/xlogwait.c b/src/backend/access/transam/xlogwait.c index 156a733ff29..6d19343b2a5 100644 --- a/src/backend/access/transam/xlogwait.c +++ b/src/backend/access/transam/xlogwait.c @@ -252,6 +252,15 @@ deleteLSNWaiter(WaitLSNType lsnType) Assert(i >= 0 && i < WAIT_LSN_TYPE_COUNT); + /* + * Avoid taking WaitLSNLock if a waker has already removed us. Only this + * backend can set inHeap; other processes can only clear it. Therefore + * false is conclusive, while a stale true is harmless because it is + * rechecked under WaitLSNLock below. + */ + if (!procInfo->inHeap) + return; + LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE); Assert(procInfo->lsnType == lsnType); -- 2.51.0