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.94.2) (envelope-from ) id 1uTmG3-009iXj-MY for pgsql-hackers@arkaria.postgresql.org; Mon, 23 Jun 2025 18:51:07 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uTmG1-005fxe-QU for pgsql-hackers@arkaria.postgresql.org; Mon, 23 Jun 2025 18:51:06 +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.94.2) (envelope-from ) id 1uTmG1-005fxW-DF for pgsql-hackers@lists.postgresql.org; Mon, 23 Jun 2025 18:51:06 +0000 Received: from mail-ej1-x62c.google.com ([2a00:1450:4864:20::62c]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uTmG0-003avo-07 for pgsql-hackers@postgresql.org; Mon, 23 Jun 2025 18:51:05 +0000 Received: by mail-ej1-x62c.google.com with SMTP id a640c23a62f3a-ae0a420431bso71228266b.2 for ; Mon, 23 Jun 2025 11:51:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750704663; x=1751309463; darn=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=zz4jnsIV0Uo6/B9YdkNWnY6sEa+EQjC/hnGswImLEh0=; b=mkrfKNpSWOxlHTkHaun4J3+Qal86+qOAFmaz7113WdFY0WV9ayCKuuCxFcBUBNYZzz Crdv6+3P2W12q/7kzHBKgjyQqH+P0yoixd2LtE3JBKDMMYG72dCgoaXRDYSWryYMp5d5 inqgtxyar3DQrRMOFdVhofTP0sTYfrG1N4Y1uqi0y9q2Jr7wGDL3VSI3x/eZUu9TUs5X 0bwEaD0hWSOfkg/f/oByWuyhNdYvFwDtrODMPC0NaxqAjirexK9J4SefzWUqT9R/H7Dv AGfCrzlguNbUgNBFreGr6b+cdj/ZPnO8yaGP3ejwAUSMd+ClFsA3JQVrnqxQQVRc7xNs 6oZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750704663; x=1751309463; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zz4jnsIV0Uo6/B9YdkNWnY6sEa+EQjC/hnGswImLEh0=; b=osK4JQv54fzy8XJOxxotFQBQvufiQPw8UJhibHJVGM562qFcljBx+HwC1+0JEwkMk8 sfhe/iwdKy2NKYCC9jxWcZyhXvpwMblqpXaFIOrGT5MX0MbT8tnAw3ofTXKg/z5fCHo/ ZWAtVISiwomkyRavYIu+nMUrp4Rjk2muEi/A0hclcixRLGa3qB84FhM20rFeNotjNbZE iBelh1l1kO+VEm8axDK8CWRRqfR6u9s8R8G3ImDC7mFy4sEJhpy3dbGUuSGAfwiGO1PB te7XHs95w4Ri727xsX1kn12CgKZgTXsJtxho98ufvEILPFS/3Ro5Yq9dPTwyme+5Z56i n36g== X-Forwarded-Encrypted: i=1; AJvYcCUrp69TNfhF0JNaC0lQH9MYzy4JG/RPcgKJNyEEaaEeW21E634wSIl1MQHu8pKAObiWkGVtuPCat6sQwh/L@postgresql.org X-Gm-Message-State: AOJu0YwuaAGyZQIRzNrD21+lsi/udjX2pYF50KAnu/ud9UpAdFLfze36 kudoCx6hnMoUIfiYDxe/8HHWTe+8PNu9jQA593B8BoVC4SrLT7GTh7YZmzk5SW/VzW6fouzqeMm Cbj1XrCfHhWwnIOrUKwpx9KOfTqpmniE= X-Gm-Gg: ASbGncvsDxDXEh46YYeqHWAO8NYP9twLa8irBsiwUygCJt4Cyd+jb0m4Fnn/ZArmPnp /Nicn69ufOLurUap5wwJP5VGJMunEhVmBwwPglfdUlyaBaibYfb0wLV7N+bIGSr9PNaeVWiMdv8 z4ccGJFdOVk217vjDC9SnxtKC8zwKFjyMHbUgZmxVGzjJppA90AU3oSA== X-Google-Smtp-Source: AGHT+IF0VENAXuAZ7btAvDq8t/C5lQLEQcwepiqfRgtbhZsBzKd57eRAPgswfJ85phzII9dh67fNi6ozd/qR4vTY7Nc= X-Received: by 2002:a17:907:3d93:b0:ad2:1b0e:bfe5 with SMTP id a640c23a62f3a-ae0579cdd9amr1299945566b.7.1750704662283; Mon, 23 Jun 2025 11:51:02 -0700 (PDT) MIME-Version: 1.0 References: <1d12d2-67235980-35-19a406a0@63439497> <1d97ec-6841b600-3-b7b4780@40747246> <28c8bf-68470780-3-51b29480@89454035> <0a617d34-abc3-4090-92a5-ea15d45e36f6@gmail.com> <228607.1750003556@sss.pgh.pa.us> <3f242e-68518380-11-78125f00@134027639> <214ba-6852df80-9-7e0df800@134698799> <21b44-6852e000-3-a556820@87831171> In-Reply-To: From: Alexander Korotkov Date: Mon, 23 Jun 2025 21:50:50 +0300 X-Gm-Features: AX0GCFvQALiy24tT614jG5f1QDcwhzNO5QrunrL_ombtv8pMcsG0yfBmPYW502w Message-ID: Subject: Re: Slot's restart_lsn may point to removed WAL segment after hard restart unexpectedly To: vignesh C Cc: "Hayato Kuroda (Fujitsu)" , Amit Kapila , Vitaly Davydov , Tom Lane , Alexander Lakhin , pgsql-hackers , Masahiko Sawada , "tomas@vondra.me" 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, Jun 23, 2025 at 8:04=E2=80=AFPM vignesh C wro= te: > > On Mon, 23 Jun 2025 at 04:36, Alexander Korotkov w= rote: > > > > On Fri, Jun 20, 2025 at 2:24=E2=80=AFPM vignesh C = wrote: > > > On Fri, 20 Jun 2025 at 05:54, Alexander Korotkov wrote: > > > > Dear Kuroda-san, > > > > > > > > On Thu, Jun 19, 2025 at 2:05=E2=80=AFPM Hayato Kuroda (Fujitsu) > > > > wrote: > > > > > > > Regarding assertion failure, I've found that assert in > > > > > > > PhysicalConfirmReceivedLocation() conflicts with restart_lsn > > > > > > > previously set by ReplicationSlotReserveWal(). As I can see, > > > > > > > ReplicationSlotReserveWal() just picks fresh XLogCtl->RedoRec= Ptr lsn. > > > > > > > So, it doesn't seems there is a guarantee that restart_lsn ne= ver goes > > > > > > > backward. The commit in ReplicationSlotReserveWal() even sta= tes there > > > > > > > is a "chance that we have to retry". > > > > > > > > > > > > > > > > > > > I don't see how this theory can lead to a restart_lsn of a slot= going > > > > > > backwards. The retry mentioned there is just a retry to reserve= the > > > > > > slot's position again if the required WAL is already removed. S= uch a > > > > > > retry can only get the position later than the previous restart= _lsn. > > > > > > > > > > We analyzed the assertion failure happened at pg_basebackup/020_p= g_receivewal, > > > > > and confirmed that restart_lsn can go backward. This meant that A= ssert() added > > > > > by the ca307d5 can cause crash. > > > > > > > > > > Background > > > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > > > > When pg_receivewal starts the replication and it uses the replica= tion slot, it > > > > > sets as the beginning of the segment where restart_lsn exists, as= the startpoint. > > > > > E.g., if the restart_lsn of the slot is 0/B000D0, pg_receivewal r= equests WALs > > > > > from 0/B00000. > > > > > More detail of this behavior, see f61e1dd2 and d9bae531. > > > > > > > > > > What happened here > > > > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > > > > Based on above theory, walsender sent from the beginning of segme= nt (0/B00000). > > > > > When walreceiver receives, it tried to send reply. At that time t= he flushed > > > > > location of WAL would be 0/B00000. walsender sets the received ls= n as restart_lsn > > > > > in PhysicalConfirmReceivedLocation(). Here the restart_lsn went b= ackward (0/B000D0->0/B00000). > > > > > > > > > > The assertion failure could happen if CHECKPOINT happened at that= time. > > > > > Attribute last_saved_restart_lsn of the slot was 0/B000D0, but th= e data.restart_lsn > > > > > was 0/B00000. It could not satisfy the assertion added in Invalid= atePossiblyObsoleteSlot(). > > > > > > > > Thank you for your detailed explanation! > > > > > > > > > Note > > > > > =3D=3D=3D=3D > > > > > 1. > > > > > In this case, starting from the beginning of the segment is not a= problem, because > > > > > the checkpoint process only removes WAL files from segments that = precede the > > > > > restart_lsn's wal segment. The current segment (0/B00000) will no= t be removed, > > > > > so there is no risk of data loss or inconsistency. > > > > > > > > > > 2. > > > > > A similar pattern applies to pg_basebackup. Both use logic that a= djusts the > > > > > requested streaming position to the start of the segment, and it = replies the > > > > > received LSN as flushed. > > > > > > > > > > 3. > > > > > I considered the theory above, but I could not reproduce 040_stan= dby_failover_slots_sync > > > > > because it is a timing issue. Have someone else reproduced? > > > > > > > > > > We are still investigating failure caused at 040_standby_failover= _slots_sync. > > > > > > > > I didn't manage to reproduce this. But as I see from the logs [1] = on > > > > mamba that START_REPLICATION command was issued just before assert > > > > trap. Could it be something similar to what I described in [2]. > > > > Namely: > > > > 1. ReplicationSlotReserveWal() sets restart_lsn for the slot. > > > > 2. Concurrent checkpoint flushes that restart_lsn to the disk. > > > > 3. PhysicalConfirmReceivedLocation() sets restart_lsn of the slot t= o > > > > the beginning of the segment. > > > > > > Here is my analysis for the 040_standby_failover_slots_sync test > > > failure where the physical replication slot can point to backward lsn= : > > > In certain rare cases the restart LSN can go backwards. This scenario > > > can be reproduced by performing checkpoint continuously and slowing > > > the WAL applying. I have a patch with changes to handle this. > > > Here's a summary of the sequence of events: > > > 1) Standby confirms a new LSN (0/40369C8) when primary sends some WAL= contents: > > > After the standby writes the received WAL contents in XLogWalRcvWrite= , > > > the standby sends this lsn 0/40369C8 as the confirmed flush location. > > > The primary acknowledges this and updates the replication slot's > > > restart_lsn accordingly: > > > 2025-06-20 14:33:21.777 IST [134998] standby1 LOG: > > > PhysicalConfirmReceivedLocation replication slot "sb1_slot" set > > > restart_lsn to 0/40369C8 > > > 2025-06-20 14:33:21.777 IST [134998] standby1 STATEMENT: > > > START_REPLICATION SLOT "sb1_slot" 0/3000000 TIMELINE 1 > > > > > > 2) Shortly after receiving the new LSN, a checkpoint occurs which > > > saves this restart_lsn: > > > 2025-06-20 14:33:21.780 IST [134913] LOG: checkpoint complete: wrote > > > 0 buffers (0.0%), wrote 0 SLRU buffers; 0 WAL file(s) added, 0 > > > removed, 0 recycled; write=3D0.001 s, sync=3D0.001 s, total=3D0.002 s= ; sync > > > files=3D0, longest=3D0.000 s, average=3D0.000 s; distance=3D0 kB, est= imate=3D0 > > > kB; lsn=3D0/4036A20, redo lsn=3D0/40369C8 > > > > > > 3) Streaming replication is restarted because of primary_conninfo guc > > > change and reload > > > The WAL receiver process is restarted: > > > 25-06-20 14:33:21.779 IST [134997] FATAL: terminating walreceiver > > > process due to administrator command > > > > > > 4) Standby sends an older flush pointer after restart: > > > Upon restart, the WAL receiver sends a flush location (0/401D448) > > > derived from XLogRecoveryCtl->lastReplayedEndRecPtr, which is older > > > than the previously confirmed restart_lsn. It is important to note > > > that we are sending the lastReplayedEndRecPtr which is the last > > > successfully replayed lsn in this case: > > > 5-06-20 14:33:21.796 IST [135135] LOG: WalReceiverMain > > > LogstreamResult.Flush initialized to 0/401D448 > > > 2025-06-20 14:33:21.796 IST [135135] LOG: sending write 0/401D448 > > > flush 0/401D448 apply 0/401D448 > > > > > > This is done from here: > > > .... > > > /* Initialize LogstreamResult and buffers for processing messages */ > > > LogstreamResult.Write =3D LogstreamResult.Flush =3D GetXLogReplayRecP= tr(NULL); > > > > > > initStringInfo(&reply_message); > > > > > > /* Initialize nap wakeup times. */ > > > now =3D GetCurrentTimestamp(); > > > for (int i =3D 0; i < NUM_WALRCV_WAKEUPS; ++i) > > > WalRcvComputeNextWakeup(i, now); > > > > > > /* Send initial reply/feedback messages. */ > > > XLogWalRcvSendReply(true, false); > > > ... > > > > > > In case of step 1, we are sending the lsn of the WAL that is written, > > > since we have slowed down the WAL applying the replay location is > > > lesser. > > > > > > 5) I have added logs to detect this inconsistency: > > > This leads to a scenario where the standby tries to confirm a > > > restart_lsn older than the one currently held by the primary: > > > 2025-06-20 14:33:21.797 IST [135136] standby1 LOG: crash scenario - > > > slot sb1_slot, cannot confirm a restart LSN (0/401D448) that is older > > > than the current one (0/40369C8) > > > > > > If a checkpoint happens concurrently during this condition, it may > > > trigger an assertion failure on the primary due to the restart_lsn > > > being less than the last_saved_restart_lsn. > > > Currently this does not break physical replication, but I'm not sure > > > if the gap increases to many WAL files and if the WAL files get > > > deleted, how it will behave. > > > > > > Attached the restart_lsn_backup_repro_v1 patch changes with which you > > > can reproduce the 040_standby_failover_slots_sync failure. grep for > > > "crash scenario - slot sb1_slot" in the logs. For me it occurs with > > > every run. The reproduced logs > > > 040_standby_failover_slots_sync_publisher and > > > 040_standby_failover_slots_sync_standby1.log are attached. > > > > > > This proves that the restart_lsn can go backward in cases where the > > > standby is slowly applying. But this has nothing to do with this > > > thread, I felt you can commit the assert removal patch. I will > > > continue the analysis further and see if there is any impact or not o= n > > > physical replication, and we can later add comments accordingly. > > > > I think this thread now have well-documented cases when restart_lsn > > goes backward. I suppose the first thing we should do is to remove > > the assert to make buildfarm stop failing on this. I've prepared a > > patch with revised commit message. Then we can focus on documenting > > that correctly in the code comments. > > +1 to proceed this way, one minor suggestion we can include > pg_basebackup also in the commit message as I noticed this can happen > with pg_basebackup too. Thank you! Pushed including your suggestion to mention pg_basebackup. ------ Regards, Alexander Korotkov Supabase