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 1wPy5r-001BSo-1f for pgsql-bugs@arkaria.postgresql.org; Thu, 21 May 2026 07:45:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wPy5o-009dt3-39 for pgsql-bugs@arkaria.postgresql.org; Thu, 21 May 2026 07:45:21 +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 1wPy5o-009dsv-1j for pgsql-bugs@lists.postgresql.org; Thu, 21 May 2026 07:45:21 +0000 Received: from mail-yw1-x1133.google.com ([2607:f8b0:4864:20::1133]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wPy5n-000000004Dr-2rQw for pgsql-bugs@lists.postgresql.org; Thu, 21 May 2026 07:45:20 +0000 Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-7c0dea734b8so54295777b3.3 for ; Thu, 21 May 2026 00:45:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779349519; cv=none; d=google.com; s=arc-20240605; b=BNTFirPJuFd1HSULTj+7anWemJbSEst++FhNtZP4DVvWgim2IB8cNgSggwFQV1kHVM sx5B/Q4BOqUxe3j2IUhhZ1Op2S6bB4EiMRllvxAPGdGPwdaV0B97vKKBDSPt8T9XITZH escJJCsPKJ27HJlAmntJifImTgAkgi9kyZLUjU6Wq+wWxicaOrdmPYTFpr+5F53Qhk9c UqBh7gE7ZZMlv51qMCxtWdRQd4EppL90mgVdOLDuk1BtwLjvmelfxyShRBZ9ZwA3RrOI hV01n5w5R1I95gvMiYAIDTSuheqKEjzirgwBmuYtpf+Iqd/warm7tNFH1KBxqbNwKnAv P39Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=38y9frqoEcg9z8+9uGkSU4Prc6PNbxtzfVKvUPgLt+U=; fh=RaJ827L9ChzrNwVgMqTOdQcGiyHOB/0Pl11/vwoy22A=; b=PCN7dz9fGy7FpzHpmjitJboX5VxxvnnW4WLM3i24ggbZZoBwL2F5EgWGNL5SXS9xMQ IJdRF39Muz0l0kd+Uux2E2+8M1WlTX/MIvPGkRbYAUmY67VtwUu0U/CnTwR6JK/FafqG mDfIimoMUDgmDBYj4Jyh5fRZaGm/wpudS1DEFoA20K2KyHZMUEgLMmIl3huAUXSPfgId /GKksvmq1Mbki6cyQgml9ER+90tQrzg77S0B8Gv9qhgOke2LVd/lZUy5EY1w4pby2w2a JqrL0WAGHq4CrLMcf+z3xHbARuN1l86kG62aR9+lbefO9TbeqLToiE6dLMR7/67EiMGA zTJA==; 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=1779349519; x=1779954319; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=38y9frqoEcg9z8+9uGkSU4Prc6PNbxtzfVKvUPgLt+U=; b=mzE8YLpgUf849aHJ7+NBetLVmI7Y1BS0PxbDNATLsgij6BA5BpG83Mca6JCImIH9wT taDDTG5TPQF+I1TWKCBMhrSRfc9TGrSu0uuDsJyiGLf26qmOnLPqaMhLejnZ7ezYznPq 7zOsAwKcrgVbSaiCKq8e0TPu6Zmi4kx1qJW4VjH+BeCNuy5ARGTDCEt+7Tvk3/YURbKm FoNrn2G+Zy6p9f24KZjvOip2ztuhfc51k+jiid1fUGidKtAKsBt0kjD23XOzEBhNqPt+ R1VU8OwLeoQ3u2I61hWvo9BCQguv6Fjoitn1uyQ6xobVrSHC8JdTYwVLXC7JnSI0bQ+7 wmkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779349519; x=1779954319; h=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=38y9frqoEcg9z8+9uGkSU4Prc6PNbxtzfVKvUPgLt+U=; b=rZHOUFQ631JBY7RrMJFPH9J9l42bXHgSXVG5Opbe1E5FybdtumK8ux3L95baR44/31 MAuKvFRgZBw3MxNbb8zEqwTQoryv+n1gE/mqfNtfOCBgK8iZ9azrwjG5socx3A2QHQLR IxOPQ5QpRHpiX1DKgSoD3Z9KdY+CHH4boRVqlL6Omb4ZkbJb7aoHOVOeOzPrOrJP0654 RpvrpP13D9hjNsWhigmXlEOuEzNTo9NwgTGot930iATzArb9C8OIbEDCSWiJDBU3yRLl hhmATGcbF2FtsbrAX0CgT6fbf2ky6yQaAb5TWrzjbiYldj6+cAKfyo5hAqh6uHXiUAy7 vYTw== X-Forwarded-Encrypted: i=1; AFNElJ9omC35Wp39W74Kng26QJMGf1F5dXTJJ29/wZAHbO7effujO6RVv/RrWuAIcmXPW4p5V8/MZHCGJdcx@lists.postgresql.org X-Gm-Message-State: AOJu0YxIChXAS4/3bJNqYR/XtaaR9FZC5a/jQiKcFuix66XokNp1Nxyt ypc/DIr8fcyRClPebyJxrgvOBYoizKss9oxLuTq7hQKv+6humC1ewoYkuOlAWM4ab0uq9+tDiln 1NtIQSHN28/9M6zk+hqRBnFBT2ZBdEQg= X-Gm-Gg: Acq92OGdEUCmR/nHZ5qMTKBn4goikEgv2Ip6QQwmRo3kehmkBj46mqkDxEGpH6XAixI TRYtiYfJqjNwKpMaaWVS5jgwoGG08yqIyuthkXJjqm32hSXC0FdeZkVl0ykgHkeo+HLv08TDxWQ WUBYgvlS2+hyMJvzhoC+c5xDPJf40fDKeSWso/A53rIoJWbFhUr1X76VNElajt/k4FO9eXkDN69 wTAPsoLSAHkTnqFXgjWuW8ocR3sN0gi3okFxUUsTxS07dExC30RHC8nAb/yWmJpfsrX0MYVR0ko 0KNc8g== X-Received: by 2002:a05:690c:e347:b0:7b2:136d:2436 with SMTP id 00721157ae682-7d209cd3626mr17455517b3.8.1779349518951; Thu, 21 May 2026 00:45:18 -0700 (PDT) MIME-Version: 1.0 References: <19490-9c59c6a583513b99@postgresql.org> <46FE61C9-F273-45FD-BED7-0F8CDA6EB992@yandex-team.ru> <46DB3CAB-EA1C-41A5-9D6D-5F913A2AAF66@yandex-team.ru> In-Reply-To: <46DB3CAB-EA1C-41A5-9D6D-5F913A2AAF66@yandex-team.ru> From: Ayush Tiwari Date: Thu, 21 May 2026 13:15:07 +0530 X-Gm-Features: AVHnY4IiiF3v5HKiBWP8fx-lq-bjK9An8im8KFtc-L91RzqpoxrmVUzPCvnU270 Message-ID: Subject: Re: BUG #19490: Streaming standby on 16.14 stops applying WAL on MultiXactOffsetSLRU when primary is 16.8 To: Andrey Borodin Cc: Marko Tiikkaja , radim@boringsql.com, PostgreSQL mailing lists Content-Type: multipart/alternative; boundary="0000000000000229e006524f1869" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000000229e006524f1869 Content-Type: text/plain; charset="UTF-8" Hi, On Thu, 21 May 2026 at 12:55, Andrey Borodin wrote: > > > > On 21 May 2026, at 00:12, Marko Tiikkaja wrote: > > > > #8 0x0000654c8ae2acba in SimpleLruWriteAll (ctl=0x654c8b63e400 > > Thanks! > > This clearly points to SimpleLruWriteAll() added in 77dff5d937b1. > If by chance you will have a backtrace of another deadlocking process - > please post it. > > But it's not strictly necessary for analysis, I think we can figure out > what > happened from the backtrace you already posted. > I had a look at the code that Marko's backtrace pointed at and I believe this is a straightforward self-deadlock introduced by 77dff5d937b. In RecordNewMultiXact() on REL_16_STABLE: LWLockAcquire(MultiXactOffsetSLRULock, LW_EXCLUSIVE); ... if (InRecovery && next_pageno != pageno) { ... if (last_initialized_offsets_page == -1) { SimpleLruWriteAll(MultiXactOffsetCtl, false); /* <-- here */ init_needed = !SimpleLruDoesPhysicalPageExist(MultiXactOffsetCtl, next_pageno); } else init_needed = (last_initialized_offsets_page == pageno); ... } The outer LWLockAcquire takes MultiXactOffsetSLRULock EXCLUSIVE. SimpleLruWriteAll() in REL_16_STABLE then does LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE); and for the MultiXactOffsetCtl SLRU, shared->ControlLock is MultiXactOffsetSLRULock (set up by SimpleLruInit(... MultiXactOffsetSLRULock ...)). So it tries to take the very lock the same backend already holds. LWLockAcquire does not detect that and parks the process on LWLock:MultiXactOffsetSLRU forever. That matches every datum in the report: - wait_event = LWLock:MultiXactOffsetSLRU. - pg_stat_slru shows zero MultiXact activity, because the SimpleLruWriteAll loop never gets past LWLockAcquire to actually write a page. - Restart unwedges things briefly. - The deadlock only triggers when last_initialized_offsets_page is still -1, i.e. before any XLOG_MULTIXACT_ZERO_OFF_PAGE record has been replayed in this recovery session, which is at most once per startup and consistent with the "recurs after catch-up" behaviour. The "safety flush" the comment justifies is it needed? Every offsets page that this code path initializes is synchronously written via SimpleLruWritePage() a few lines below the SimpleLruZeroPage(), with an Assert that the page is clean afterwards. So at the moment we call SimpleLruDoesPhysicalPageExist(), there shouldn't be a relevant dirty offsets page in the SLRU buffer cache that would lead to a false negative. Dropping the SimpleLruWriteAll() call therefore removes the self-deadlock without changing correctness. Maybe I'm missing something here. Thoughts? Regards, Ayush --0000000000000229e006524f1869 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi,

On Th= u, 21 May 2026 at 12:55, Andrey Borodin <x4mmm@yandex-team.ru> wrote:


> On 21 May 2026, at 00:12, Marko Tiikkaja <marko@joh.to> wrote:
>
> #8=C2=A0 0x0000654c8ae2acba in SimpleLruWriteAll (ctl=3D0x654c8b63e400=

Thanks!

This clearly points to SimpleLruWriteAll() added in 77dff5d937b1.
If by chance you will have a backtrace of another deadlocking process -
please post it.

But it's not strictly necessary for analysis, I think we can figure out= what
happened from the backtrace you already posted.

I had a look at the code that Marko's backtrace pointed at and Ibelieve this is a straightforward self-deadlock introduced by
77dff5d93= 7b.

In RecordNewMultiXact() on REL_16_STABLE:

=C2=A0 LWLockAc= quire(MultiXactOffsetSLRULock, LW_EXCLUSIVE);

=C2=A0 ...

=C2= =A0 if (InRecovery && next_pageno !=3D pageno)
=C2=A0 {
=C2= =A0 =C2=A0 =C2=A0 ...
=C2=A0 =C2=A0 =C2=A0 if (last_initialized_offsets_= page =3D=3D -1)
=C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 SimpleLruWriteAll(MultiXactOffsetCtl, false); =C2=A0/* <-- here *= /
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 init_needed =3D !SimpleLruDoesPhysi= calPageExist(MultiXactOffsetCtl, next_pageno);
=C2=A0 =C2=A0 =C2=A0 }=C2=A0 =C2=A0 =C2=A0 else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 init_neede= d =3D (last_initialized_offsets_page =3D=3D pageno);
=C2=A0 =C2=A0 =C2= =A0 ...
=C2=A0 }

The outer LWLockAcquire takes MultiXactOffsetSLR= ULock EXCLUSIVE.
SimpleLruWriteAll() in REL_16_STABLE then does

= =C2=A0 LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE);

and for = the MultiXactOffsetCtl SLRU, shared->ControlLock is
MultiXactOffsetSL= RULock (set up by SimpleLruInit(... MultiXactOffsetSLRULock ...)).
So it= tries to take the very lock the same backend already holds.
LWLockAcqui= re does not detect that and parks the process on
LWLock:MultiXactOffsetS= LRU forever.

That matches every datum in the report:

=C2=A0 -= =C2=A0 wait_event =3D LWLock:MultiXactOffsetSLRU.
=C2=A0 =C2=A0- pg_stat= _slru shows zero MultiXact activity, because the
=C2=A0 =C2=A0 SimpleLru= WriteAll loop never gets past LWLockAcquire to actually
=C2=A0 =C2=A0 wr= ite a page.
=C2=A0 - Restart unwedges things briefly.
=C2=A0 - The de= adlock only triggers when last_initialized_offsets_page is
=C2=A0 =C2=A0= still -1, i.e. before any XLOG_MULTIXACT_ZERO_OFF_PAGE record has
=C2= =A0 =C2=A0 been replayed in this recovery session, which is at most once pe= r
=C2=A0 =C2=A0 startup and consistent with the "recurs after catch= -up" behaviour.

The "safety flush" the comment justif= ies is it needed?
Every offsets page that this code path initializes is = synchronously written
via SimpleLruWritePage() a few lines below the Sim= pleLruZeroPage(),
with an Assert that the page is clean afterwards.=C2= =A0 So at the moment
we call SimpleLruDoesPhysicalPageExist(), there sho= uldn't be a relevant
dirty offsets page in the SLRU buffer cache tha= t would lead to a
false negative.=C2=A0 Dropping the SimpleLruWriteAll()= call therefore
removes the self-deadlock without changing correctness.<= /div>

Maybe I'm missing something here= . Thoughts?

Regards,
Ayush=C2=A0
--0000000000000229e006524f1869--