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 1wgjhi-006MfF-0Z for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jul 2026 13:49:46 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wgjhg-000vHf-37 for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jul 2026 13:49:44 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wgjhg-000vHX-26 for pgsql-hackers@lists.postgresql.org; Mon, 06 Jul 2026 13:49:44 +0000 Received: from mail-ej1-x636.google.com ([2a00:1450:4864:20::636]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wgjhe-0000000249M-14e1 for pgsql-hackers@lists.postgresql.org; Mon, 06 Jul 2026 13:49:44 +0000 Received: by mail-ej1-x636.google.com with SMTP id a640c23a62f3a-c12629c937eso355798766b.3 for ; Mon, 06 Jul 2026 06:49:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1783345781; cv=none; d=google.com; s=arc-20260327; b=llgOCicgwXp3DCT4c3hUTOPtBpE5xfJYhoOZF6fT1UUPrkptK+U7kJm6XbMVk5NhzO P9nXxugHYbC6wjPnMGYQx/bNI9t0eZlMf8KQJp4C4+q4YAyAmMJXlIcIeam/dC+Nc7wm QwCBQ3mEiup538o7M/3wkmjWvPmkB0adQB4PN4AxoCjL1Vn50JJgP6XXCW6KfLyTMYRa kqE5vwWNwEqbuK6gsc/nUK0G5Jh/7LshAJzsNC8YBBZEkgFZNmQYSYS5gbmfOL7dnjID zf3Kd0yEGC5lBMkx55FzNxR1COzS//vlNEcKFls4hgrTzWB1W5fREzAVjHHOKtixEnN3 Emzw== 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=5Po5jDoKTXgxW+PLqxCQtL3z4Md4ZKjrYVh4KKuvsic=; fh=qqxF+KoX7C9MbHYz/25lkFV0R3yWFBnHYOFnfFyvq4g=; b=EnrFH3bS5v7h+C15J1dUyhoeSBrIjXPdsn4o/ogNb107u3409nOaeP8il/+AdzQNSc NDKWWxZrcBo6BVwY6GiF5YJj/kA7KbeFWMd/W+pqjE0p7Nj0CCekQmagx2+t4ZQx9Bb+ s1+wlIhn17nJPUc/Ts+QVVxPMleGxqjUQQUBBDTp9Xh4fZxjmMYDJNGKF7qZxuvH49Dc vmF+tG/T+syHCOR3UPNMp86mndHl+UwnWHy/ED5ZcynfuuoofolEQVMjw0YxyRdRTXoU YsJV2ydhzsTR/6VRrqIHYFH/XfwZDLUIx99pmzXRnxoS4nPAi0NPqaSKUhOREaNFrySp FIMA==; 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=1783345781; x=1783950581; darn=lists.postgresql.org; h=content-transfer-encoding:content-type:cc:to:subject:message-id :date:from:in-reply-to:references:mime-version:from:to:cc:subject :date:message-id:reply-to:content-type; bh=5Po5jDoKTXgxW+PLqxCQtL3z4Md4ZKjrYVh4KKuvsic=; b=h/i+jsQ5oYZ0RGWjY8wdIVTh0abaW4jVxr1Cl3z1IeZY1cr90XbSMorqGX7rrrRqJV bSRW8HFe7zclv5Ti6Or7FW2YaCVWnEJwV+l+VAo6FjYQjbNV1TGlpq1ItOnuz3NCaQVr w+JdugXdOiLdw7vmvimzEHernMt9PUyhmIUOgKpx4n4UFYChS0hkbTNDLR598EGhxppv u6hBQ+9JYLfZpFwvllU2XJKDChDhyiQEh35Bywfh9Q5SSTQy034I12E4C4x+eJExMwJx 3wXzeZ66ZJroiJv3ag/iy6pWz5iMbkffF+oe5/mFgoxE+BWSZQFthVKt5/tZnAx3UJDL oahQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783345781; x=1783950581; h=content-transfer-encoding:content-type: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 :content-type; bh=5Po5jDoKTXgxW+PLqxCQtL3z4Md4ZKjrYVh4KKuvsic=; b=PDb7cd0N1GVH4Dzzb4y3OyZOvQiEBiCSmjVLSh5T4GQ+HBElR4o8oyOsXikjlMWifB iDNFrkaQ9r5NvUnEkEwZTeAJkRkshyjO4WCjO2Ewjqu/UyZse3vaQhJ4qGeNwnXOEeFw cKliSkw1JEHJFk797BNVLRS12dUJxnuL3AjKq6zTMEXf3dheuprq4Dl8bC99GhtR3e30 h1JafhSQ3IQWbQUXnHw8NWM9T9hK5alz4JJ44G90P+lL6XE1hzYTlFKhm9TWWKq19gOB TSjnx59si2FP4CpBFQeS+//voZOSWkvqxtHaNEz3nxKt2pxARlgARnFBNpbkR96S3lDI 2B2w== X-Forwarded-Encrypted: i=1; AHgh+Ro5B8YCe5nfbTcqbbl9z50ecYCsZJwYS4WyUd0Bg0V5fqdVQXpZZhmdsVlOuYs4JdpvxhmnO9K9WzOKGUFc@lists.postgresql.org X-Gm-Message-State: AOJu0YyPI2csz4lGgj8/2XPFscYY/DpQhA0kfM7QrAr+qGJRmkvPiuTp 6vO4gpVDYnVaxys6yQaocr9zyiAJCCI9G97ke0pLpHbiPZi0bwpqDYkYZ42DsAtGYzfCHUETpEW K5YDc6j61998DOTP6bQ5Qynz4b+gW2aY= X-Gm-Gg: AfdE7cl8PA+AmTQy8czUJuL8jwlJt161/IgaJRbRc6nAchDGNkU1e28694eM/2gp2XS aJ0BuLavGx/rFEWuullDvbayGe+5p8benX6teZoeR/7m9wpBxaYitjfVBfvtHJwILSSlNVcmNNK vKiNQobE0sfTEeg9pAQsSfFmuou2fFJdJQBioeRgWkfKJd/GFLGT15uVW0SCHVPXIIZubbyc9Tp 3F4fZPNoePA8+f4NQzeHvpC6j4I703hD00LRGoI/YqtitrQEJQBfEQbtNrnIyEb4sPefGBlE/Es yJIQWfVoGnFU4gqqTkkdaLZxPQpBbiDxx28DbHRU6uB2cuk8Zi9B5q3gSItKrLfm1/7rmfTY8RW sizybxAdU2Sfj4DpEIoJCJGzXxx0= X-Received: by 2002:a17:906:9fd0:b0:c12:add7:b97b with SMTP id a640c23a62f3a-c15a6738f60mr39574166b.29.1783345780225; Mon, 06 Jul 2026 06:49:40 -0700 (PDT) MIME-Version: 1.0 References: <1959506.1775527693@sss.pgh.pa.us> In-Reply-To: From: Xuneng Zhou Date: Mon, 6 Jul 2026 21:49:26 +0800 X-Gm-Features: AVVi8CfA5MRMA2vC2JBudpQJazi2ccAQrdeYV8ny59yamfFa05E8Y-j4EQ5OHiw 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 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. Replay = implies that the > > * WAL was already written and flushed to disk, s= o write and flush > > * waiters can be woken at the replay position to= o. > > */ > > WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_REPLAY, > > XLogRecoveryCtl->lastRe= playedEndRecPtr); > > WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_WRITE, > > XLogRecoveryCtl->lastRe= playedEndRecPtr); > > WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_FLUSH, > > XLogRecoveryCtl->lastRe= playedEndRecPtr); > > That's not wrong, but I've got some comments: > > 1. It's reading XLogRecoveryCtl->lastReplayedEndRecPtr without a lock or > atomics. That's ok, no other process modifies lastReplayedEndRecPtr, but > 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, XLo= gRecord *record, TimeLineID *repl > > /* > > * Update lastReplayedEndRecPtr after this record has been succ= essfully > > * replayed. > > */ > > SpinLockAcquire(&XLogRecoveryCtl->info_lck); > > XLogRecoveryCtl->lastReplayedReadRecPtr =3D xlogreader->ReadRec= Ptr; > > XLogRecoveryCtl->lastReplayedEndRecPtr =3D xlogreader->EndRecPt= r; > > XLogRecoveryCtl->lastReplayedTLI =3D *replayTLI; > > SpinLockRelease(&XLogRecoveryCtl->info_lck); > > > > + /* > > + * Wake up processes waiting for standby replay, write, or flus= h LSN to > > + * reach current replay position. Replay 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, xlogreader->EndRecP= tr); > > + WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_WRITE, xlogreader->EndRecPt= r); > > + WaitLSNWakeup(WAIT_LSN_TYPE_STANDBY_FLUSH, xlogreader->EndRecPt= r); > > + > > /* ------ > > * Wakeup walsenders: > > * > > * On the standby, the WAL is flushed first (which will only wa= ke up > > * physical walsenders) and then applied, which will only wake = 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 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. -- Regards, Xuneng Zhou HighGo Software Co., Ltd.