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 1w7tbe-005oPR-1R for pgsql-hackers@arkaria.postgresql.org; Wed, 01 Apr 2026 11:19:30 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w7tbc-00GzrT-2z for pgsql-hackers@arkaria.postgresql.org; Wed, 01 Apr 2026 11:19:29 +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 1w7tbc-00GzrK-24 for pgsql-hackers@lists.postgresql.org; Wed, 01 Apr 2026 11:19:29 +0000 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w7tbb-000000028A2-1DLk for pgsql-hackers@lists.postgresql.org; Wed, 01 Apr 2026 11:19:28 +0000 Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-35d971fb6f1so3492400a91.0 for ; Wed, 01 Apr 2026 04:19:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775042366; x=1775647166; darn=lists.postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=jP3VZS6SWVzkbrkSHTiFh+hVmEWl37nIfcQUSiwpvT4=; b=aS3xsMEkkR+n7ZRJuyDxY4re1/jt4uigyv91gh6jZMWINPduwp9rA/gxJcgddm8HsT rtMjKIXoblIJvtmC28FNve9P0GbKlalljSed0VV5ue+IVWlvasLCGB1btUBuENhTm43Z 6KgnSVMFaCaJxPhLI20fizyhqyAs8Xone1OdE8qn2ymhsYsd/VKvA4klMu125Z9t/b6U l3lKOEGO+mcmmdIvnI7MoSiRGA/66h58EYEdamD2qZq11+27QG3C0ZYSi9P3WlYnIyIK yIx7Z+8b/bKmNjJoCyMbbAGl1p3zSI7HQ+vMkmeeo+5Ttot0GO2ynFgq1I/UaD0Td2LH DpbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775042366; x=1775647166; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jP3VZS6SWVzkbrkSHTiFh+hVmEWl37nIfcQUSiwpvT4=; b=CHCc8qfqg5ibY++J1xhaLOkx80h05caLeUW2hsnbH9UKXbBFb8TXI1XlRrjPcZetYS NUbmmBBSb6A8BbRoixBgavX+hlFPQlwz+2SrR6hVAb7o8w3F1lbzl3h9/AIc6fNbjzme VfIEVwvntY8/q3x8mkKkSYkyp59Ba2cEMwhYzmgjFvgt2VU5zOQ2RNK4lJa1rklPwC8G hQlL5YTVbZ3wD6efltOV4sKFj0vCOm/j1v9SmYu6OpkmFuvFBICcGGPvdlu2AMQ7PM9y 6f09llZ5nvi0vI8E4jklNslnVxQdonl0EnZBlcVdbjGCIIw3Bd8srjwDfq2DCl6hPwDG HkcA== X-Gm-Message-State: AOJu0Ywxkg4+tWosnJq4HifKdsmyqXKrRUGFR9td7hpbi/DEGJnImwYv fybaZl3nqpUCba7P9UVHWmyS6pyK+BepkPHHSVF9zrmAP0gRTnhPde+E X-Gm-Gg: ATEYQzzLXkP2FT5sV7JdER8wC0zeHpjJB/gMNyfsQH/r3sgXAuRdBTZGjy9Q3X4u8Ox N+pJdOSn86e+RSnJTX1Q+ZNNtN80VaJx+ahfDbjV3UGTspmeGORX0tx3G/OwTzPFqhSc337URjv n2ufKXNYapTwttRJ47n/dON+mLLGrtqU4pr4BT5EQ/R7gR+VcJodRqqhUmOFJAtwqLwKK5zP2LC D1q83sYkpSEviab0sxyHVtMaN4J/mp1KudepgsB2VyQiZbk7bl/sTzHNzmRUfrdxrKG09nvHHJC 3EfvWs2Rt5eDnfpYU3UEjPuikk/m56c7Jjt+fwb0dZjieBi0D1h+KckNvCF1VJbjABPj5r+eZ2b 78GEFXrdnbVsmFh2DVBoH6vU32R13ReN2r6IU8ou3wjinuFMktr4/rvFVGj3kkabMnDBH5hzK2N b1NuOICPPIeo3DhBTwgA== X-Received: by 2002:a17:90b:4cc2:b0:359:7c55:c166 with SMTP id 98e67ed59e1d1-35dc6ea115emr3350555a91.7.1775042366222; Wed, 01 Apr 2026 04:19:26 -0700 (PDT) Received: from localhost ([31.223.184.166]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dbe40586bsm4161056a91.0.2026.04.01.04.19.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Apr 2026 04:19:25 -0700 (PDT) Date: Wed, 1 Apr 2026 19:19:18 +0800 From: Adam Lee To: Heikki Linnakangas Cc: pgsql-hackers@lists.postgresql.org, Michael Paquier Subject: Re: [PATCH] Fix minRecoveryPoint not advanced past checkpoint in CreateRestartPoint Message-ID: References: <038d97bc-fbe4-4d99-b7a5-e468ef361123@iki.fi> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <038d97bc-fbe4-4d99-b7a5-e468ef361123@iki.fi> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, Apr 01, 2026 at 12:38:15PM +0300, Heikki Linnakangas wrote: > > My RCA: > > > > When recovery_target_action=shutdown triggers, the checkpointer performs a > > shutdown restartpoint via CreateRestartPoint(). If a CHECKPOINT record was > > replayed shortly before the recovery target, CreateRestartPoint advances > > minRecoveryPoint to the end of that CHECKPOINT record. > > > > However, any no-op records replayed after the CHECKPOINT (such as > > RESTORE_POINT) do not dirty pages, so the lazy minRecoveryPoint update that > > normally happens during page flushes never fires for them. As a result, > > minRecoveryPoint in pg_control ends up behind the actual replay position. > > Hmm, what exactly does minRecoveryPoint mean? The current behavior is > correct in the sense that if you restarted recovery, you could still stop > the recovery at the earlier LSN that's the minRecoveryPoint in the control > file, and the system would be consistent. I agree it feels pretty weird > though, it would seem natural to advance minRecoveryPoint to the last > replayed record on a restartpoint. Yes, the system is consistent either way. But for the shutdown action, it would be natural to advance minRecoveryPoint to the last replayed record, same as the pause and promote actions do, whose startup process don't exit and have the chance calling UpdateMinRecoveryPoint(). > Perhaps we should simply call UpdateMinRecoveryPoint()? That would cause the > control file to be flushed twice though, so it's a little inefficient, but > maybe that's fine. And calling UpdateMinRecoveryPoint() still needs to explain why later the codes need to ensure minRecoveryPoint is past the checkpoint record, to me it doesn't make things simpler, but I'm OK either way. > If we go with your patch, does it make this existing logic below obsolete? > > > if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY) > > { > > if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr) > > { > > ControlFile->minRecoveryPoint = lastCheckPointEndPtr; > > ControlFile->minRecoveryPointTLI = lastCheckPoint.ThisTimeLineID; > > > > /* update local copy */ > > LocalMinRecoveryPoint = ControlFile->minRecoveryPoint; > > LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI; > > } > > if (flags & CHECKPOINT_IS_SHUTDOWN) > > ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY; > > } Indeed, no need to check lastCheckPointEndPtr, replayEndRecPtr is always >= lastCheckPointEndPtr -- Adam