Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wgk93-006Mvq-39 for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jul 2026 14:18:02 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wgk92-00164b-2a for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jul 2026 14:18:00 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wgk92-00164S-1K for pgsql-hackers@lists.postgresql.org; Mon, 06 Jul 2026 14:18:00 +0000 Received: from mail-ej1-x630.google.com ([2a00:1450:4864:20::630]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wgk90-00000001rG5-1apn for pgsql-hackers@lists.postgresql.org; Mon, 06 Jul 2026 14:17:59 +0000 Received: by mail-ej1-x630.google.com with SMTP id a640c23a62f3a-c126eb4e228so342509266b.1 for ; Mon, 06 Jul 2026 07:17:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1783347475; cv=none; d=google.com; s=arc-20260327; b=JTG0LxOFMWe+LcFo8Pq3ZF7NKVvaTh+AdyLpttsRFOcmNciSf4bL2yll0PD1SZ7wvl kjbGILyT2qog7WTtNfT2YhQnzUloxVfIXx6I6qkvaOK+dCeoLqZBinbdnR2ITWI6Pv3W ftMC38oLvhE2hV85kaLLfB/1Y2KQxuUCny3rRGfjUC0563Xfw0xWAVVFygDJChjt9YxL bV+sZGJ+dkO2N2GynkejzSefskXf64jGPo5G22j0XeoCmROZdYgNOTWkJ2/OgBIcPifZ u6HTqgP/ZMoWEPKp7hsGIUjfYzANr+Ap7WDZVsHu7hksSXHLlGoOpwW3AGhOBTpdMGwg sGhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=aTmqH17YiVzK6ZGYhAswPbz08MnIDG+AITvHfyqKV1o=; fh=c/3W3+RMHl2tgUgoXcPcdnTruMmgtt6gvLCDy/hFhTw=; b=b9XYk1m3MO0XejHRs+aZxknJRoyNOvipJymJ54LjOpNCG6FT/7M8LKf7WuI3leOmQ5 bv7+5ZsZ4VTC0Pl7uRdd6jSaLIZt1cYqXVdX1i3dFa6fxWKi/Du6OJtQMQDNlHX01LdX N2K2WGB3+RvGjN9HlFCv2ILRUBK1HeayMT8xk+Roy6RyYtuvGvCOkf4jH5d9wTnehYfm YkgsZAbrOVcwIl8HUP1n5kiBvOOqNFaJNrqad9vuSu2kvdokr9kL5IR0DcX+CTh76Dqn zp1Fman4TuOz3IVtoZBdrMuHjh2+v0Cma2kdjCulr06fPuvAkSE2h5Z24GNKiJc+q4fn MY2w==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783347475; x=1783952275; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=aTmqH17YiVzK6ZGYhAswPbz08MnIDG+AITvHfyqKV1o=; b=q40OafscvHJbH8uEUNFmskxHE1STb75bHM3C011+bfYmrbw1LlSTm5FQTfkQSUUaWH 1NDVnFpRr6SWKSdFmf/SBayaQXfGdVUEb01DXNG+2Av5VqtuJF5JY1aAmi2AByyb6JMx qP4zK44TK2kFVyOjbL94lO/VhcbSRFiYOUfLKIBl9L3DzYCcsRpg50S4SAGonOhEQmPI Xw956s9kcrQsmdeNyuAILV1sr+EkCjTJhYYj8DbYCYRFS7dE38rPPGHAR+rCh2BgK52I uW7eruTvFhlqYhDANi7Cb6lxQ7Bv0+0zG3v7mrrlGCnIjPiUFxeZRUN2kz16Z1kh037C yEBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783347475; x=1783952275; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=aTmqH17YiVzK6ZGYhAswPbz08MnIDG+AITvHfyqKV1o=; b=YujecqFZtP9KmLHBfbHatt/pWEFE9iHia9s3hrdS4W50R5eSa4f0JtQpBzyKJVPMT6 g9ruer8r6HdRrYlb0fs+UA4HZMRSXhZcGglxWF8pFTCEgiw5F6vMuvkKCmSM4366Wz29 DWOnE1Vq1iadVctJx14gHmVeUrzQA0p312dAq5znvrPs1MlPtDKb4tqM+WuAyibp52o1 Fu9pDtX2OGy7GdHm9UaRJ33JF3I2a3PDwZCk/WbsAIiWkvInyxeV65oQfrejGZD3dktI 2JZeoGraeizLY3FLt4moWoTWOdNZLj5A4cC5sp08LtbbAmeKCDifHjY3Q/aNBW4YAcDc axBQ== X-Forwarded-Encrypted: i=1; AHgh+RqOiG4TWAFYCTp+gE08Y469QzKG2azCGAv+IrrVmV4vHv7XawJcOb2f6cTv07WEVRlZmGW+8gInY0GxVp/r@lists.postgresql.org X-Gm-Message-State: AOJu0YyLilU0aTVjzufynFd/KXtdEAu/5ziLuR6CW6dxvQx6BZyfSeft fna9zhIOrlbtyn+oIwCUDniWgZOoX/mn34wxJ2zmOD/g1O/f5HAzPvranLoID910hULxgnqcL+C dPtUaat5gHbecwmERe8FqmRhCcx0XEaE= X-Gm-Gg: AfdE7ck1emHGfTAajeAnRSjDgoWUEGSh/2l16RIqI2UaOPdsuBMmaH5gsXDXRkXVblY zn9+X28YLJk2u1USWOYVhevOAtUsubfEXl+b7fMUNp3qrGOgx+60xH44vvBQ8kJ0zHbxvbmCq3f AJPiH+bsZymEel6pLbEaqAEO0/XF34cG5cbPmybKvr+YHurH2WMbuRlsP9Ev30VwcEs7YwROHCy LJeeyIpYFAgVKB8gguzB2NQkiMi/8cfWXgFkzMhfYDA/LpyJ8nW4lU0nbxJVbqEYbfNhrZU4WYX ePGeq9Q0haN5Fw8R6p6HcL4IaOIVD/RAB6PiAJrMG7v7xMyBhRcVkCyVCq/X/HIQvPp9a4FKUUv 1li2eZ+frDYCLK1L+8YoVyP9wynI= X-Received: by 2002:a17:907:97c4:b0:c12:29a3:e348 with SMTP id a640c23a62f3a-c15a684dd8bmr44835466b.27.1783347474802; Mon, 06 Jul 2026 07:17:54 -0700 (PDT) MIME-Version: 1.0 References: <1959506.1775527693@sss.pgh.pa.us> In-Reply-To: From: Xuneng Zhou Date: Mon, 6 Jul 2026 22:17:41 +0800 X-Gm-Features: AVVi8Cd1b4IrJVUrAtaQJ_Xegd4i2mBWgwYqb8pRCkNzJ6AkPMv5bbNuuMfjIK0 Message-ID: Subject: Re: Implement waiting for wal lsn replay: reloaded To: Heikki Linnakangas Cc: Alexander Korotkov , Andres Freund , Tom Lane , Peter Eisentraut , Thomas Munro , =?UTF-8?Q?=C3=81lvaro_Herrera?= , Chao Li , pgsql-hackers , Michael Paquier , jian he , Tomas Vondra , Yura Sokolov Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, Jul 6, 2026 at 9:49=E2=80=AFPM Xuneng Zhou w= rote: > > Hi Heikki, > > Thanks for looking into this! > > On Mon, Jul 6, 2026 at 7:04=E2=80=AFPM Heikki Linnakangas wrote: > /* > > > * Apply the record > > > */ > > > ApplyWalRecord(xlogreader, record, &replayTLI); > > > > > > /* > > > * Wake up processes waiting for standby replay= , write, or flush > > > * LSN to reach current replay position. Repla= y implies that the > > > * WAL was already written and flushed to disk,= so write and flush > > > * waiters can be woken at the replay position = too. > > > */ > > > WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_REPLAY, > > > XLogRecoveryCtl->last= ReplayedEndRecPtr); > > > WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_WRITE, > > > XLogRecoveryCtl->last= ReplayedEndRecPtr); > > > WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_FLUSH, > > > XLogRecoveryCtl->last= ReplayedEndRecPtr); > > > > That's not wrong, but I've got some comments: > > > > 1. It's reading XLogRecoveryCtl->lastReplayedEndRecPtr without a lock o= r > > atomics. That's ok, no other process modifies lastReplayedEndRecPtr, bu= t > > it feels a little dirty. > > > > 2. We're now doing three extra function calls on every WAL record. This > > is a very hot path, and most of the time, we'll just take the fast path > > in WaitLSNWakeup to return without doing anything. Andres and others > > assumed up-thread that it's negligible (we used to have pre-checks here > > in the caller), but I wonder if you did any performance testing? > > Agreed, this is a hot path. The performance impact of these extra > calls doing real work hasn't been measured yet. I'll do some testing. > > > 3. There are other "wakeup" calls inside ApplyWalRecord(), to wake up > > walsenders and walreceivers. They could perhaps use the same wait-lsn > > machinery now, but that's v20 material. However, I think these > > WaitLSNWakeup() calls should also be moved inside ApplyWalRecord(), so > > that we'd have all the wakeup actions in one place. > > + 1. This makes the code safer and more readable. > > > 4. Once you move those calls inside ApplyWalRecord(), like this: > > > > > @@ -1979,20 +1979,30 @@ ApplyWalRecord(XLogReaderState *xlogreader, X= LogRecord *record, TimeLineID *repl > > > /* > > > * Update lastReplayedEndRecPtr after this record has been su= ccessfully > > > * replayed. > > > */ > > > SpinLockAcquire(&XLogRecoveryCtl->info_lck); > > > XLogRecoveryCtl->lastReplayedReadRecPtr =3D xlogreader->ReadR= ecPtr; > > > XLogRecoveryCtl->lastReplayedEndRecPtr =3D xlogreader->EndRec= Ptr; > > > XLogRecoveryCtl->lastReplayedTLI =3D *replayTLI; > > > SpinLockRelease(&XLogRecoveryCtl->info_lck); > > > > > > + /* > > > + * Wake up processes waiting for standby replay, write, or fl= ush LSN to > > > + * reach current replay position. Replay implies that the WA= L was already > > > + * written and flushed to disk, so write and flush waiters ca= n be woken at > > > + * the replay position too. > > > + */ > > > + WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_REPLAY, xlogreader->EndRe= cPtr); > > > + WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_WRITE, xlogreader->EndRec= Ptr); > > > + WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_FLUSH, xlogreader->EndRec= Ptr); > > > + > > > /* ------ > > > * Wakeup walsenders: > > > * > > > * On the standby, the WAL is flushed first (which will only = wake up > > > * physical walsenders) and then applied, which will only wak= e up logical > > > * walsenders. > > > > It becomes clear that you don't actually need the memory barrier inside > > WaitLSNWakeup(). Not sure if they're needed for other callers, but here > > we have just released a spinlock, which acts as a memory barrier. It > > might not be worth relaxing, but it does seem a little silly. > > If we made the move here, I think the memory barrier could be relaxed > since other callers are guarded by either the spinlock or full-barrier > atomic write already. We might also want to make the contract of OK, the 'if' here is redundant... > WaitLSNWakeup() explicit: callers should not publish the LSN with an > unsynchronized plain store and then immediately probe minWaitedLSN. > Another motivation for doing this might be slightly better performance > though untested. > > > If nothing else, I'd like to move those calls into ApplyWalRecord() for > > clarity (point 3 above). What do you think? > > Personally + 1. --=20 Regards, Xuneng Zhou HighGo Software Co., Ltd.