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 1w8WnS-000cn7-25 for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Apr 2026 05:10:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w8WnR-009ocP-0r for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Apr 2026 05:10:17 +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 1w8WnQ-009ocG-32 for pgsql-hackers@lists.postgresql.org; Fri, 03 Apr 2026 05:10:17 +0000 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w8WnP-00000000JvJ-00rX for pgsql-hackers@lists.postgresql.org; Fri, 03 Apr 2026 05:10:17 +0000 Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-2b24fcc2b5dso10592165ad.1 for ; Thu, 02 Apr 2026 22:10:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775193012; x=1775797812; 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=Q0hGPyyh67N8Kg18JssofTvPDak5YXxnQOWm58Jf5ck=; b=bFZ+RHqpXfsPbwP8Om7//WIm1sicOGcfelwVWVbewgWmRYWiC2L4qgCcrp/hr3RMlI j9PTo9ZWIY19HA68F2jRqDAS+xNf2XgAlDXq0u/UKRUhSeJHIqMEuV5WlTGwskBdvwnd 6Lx8K5IuEo/ti8Z2AdYq2HSOrzhds0xu+NF1DooPKFC8abtE0U6KHED7UlDWa0+nyr/c aOODjD5PX/TgnUb+d2Wm4Zj77ExCe7aR+emIlXwzgydp39aTSQLgOuIqiwIuOazV/Ncf c34+p3akxkdEdi0WhrHDG8S8hjJN2TQpNNADCv8+nHXH2vP+C+SpXR1T+TIjDsBjViym J+4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775193012; x=1775797812; 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=Q0hGPyyh67N8Kg18JssofTvPDak5YXxnQOWm58Jf5ck=; b=ZQOJaofYZaG1KBX/RxiEVrLD3mlVmXO6szhpFMJriTr5ajH5ivwKtMgivdy6o5eCDx 4BtAm2VsTnVO2WTW+sOk/GtIL4Nzdfv6gWgPdggYHlzHZ1WYWaElqK06Egbmd5CrNH3U yxM235EDiln5G9sDM/Hu6bmrVDJ1qPXUzWu5/xHQLXuE132iitbBYHc32/3RKS+Qc1x9 5LlgFWP1HugHsq2XAxpFwr1ya5EmZotDhowtCvSLGszu5LQo1qOTsl4cC4rqq9Sm5pGz LKF5cCef+/ZSQBBV7UMKf6W5ylyjcG9NnkcCFA9hg5CXNOG+AgMXhAQ/1ZlCfVkWlTHW 8Tew== X-Gm-Message-State: AOJu0Yy1DZ5WN6otA7KU0fmis4ko24ZzfDxDlUQQUE41f8eXy70giOK5 w8H4NaI+Vk1s46GzJVDpG/WSXbs22ueKfzlAh86jSsOVmb5bzwP+q0zG X-Gm-Gg: AeBDies1hZjYg153auYaRy8KIgefemwEaXchkuwX5rW/QG++GmuAwgYiLeHnmQXMOyY nj9GHJZqP68Sab/WkNTL5GP+N0qhj9gMjE+Y7S4EnenfoJUgpNLk+YmNxHoYUqxP1jPMgOSJPCl IZIgG4DpHI8N5ln8WWrFnipNqft3SO3Ic4Q2okCc/0UfMe9sS/LkmEBgGBtlIHvCnG9zPO4RWnK KK7cfehr9oYunXqDIb2qqgiLRncVjL8h82seLVfQlZZQ8wO1vSRhnH9QcQk0jzIcTfs4W54tZ45 ZyfLUV1mg6vTr75Xnlthip907sY8EfKhIOVzUUWJMbwZET0qmnHi/YO38758qVbXgsurtQAgcGE AJ1gotgvk4TC+Z2ccCVXA0DDKCPxJGFT2UZKkj7kvdd2fhAnCzh4AZFE0q56o0bqMTcBf/sS1ev 2zLxYVCRaS8WcuzM34Pg== X-Received: by 2002:a17:903:2c05:b0:2a9:e8b:5326 with SMTP id d9443c01a7336-2b28183277emr20119115ad.23.1775193012172; Thu, 02 Apr 2026 22:10:12 -0700 (PDT) Received: from localhost ([31.223.184.166]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b2749a34a6sm46306585ad.60.2026.04.02.22.10.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Apr 2026 22:10:10 -0700 (PDT) Date: Fri, 3 Apr 2026 13:10:08 +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: multipart/mixed; boundary="rlqg/1ddaRuGTcZI" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --rlqg/1ddaRuGTcZI Content-Type: text/plain; charset=us-ascii Content-Disposition: inline PATCH v2 removed the variable lastCheckPointEndPtr and refined the comments. Thanks for reviewing. -- Adam --rlqg/1ddaRuGTcZI Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=0001-Fix-minRecoveryPoint-not-advanced-past-checkpoint-in.patch From f639b7c0bc76ab06ff5a05c26aceb1764955a849 Mon Sep 17 00:00:00 2001 From: Adam Lee Date: Tue, 31 Mar 2026 18:43:53 +0800 Subject: [PATCH v2] Fix minRecoveryPoint not advanced past checkpoint in CreateRestartPoint When recovery_target_action=shutdown triggers, the checkpointer performs a shutdown restartpoint via CreateRestartPoint. If a new CHECKPOINT record was replayed shortly before the recovery target, the restartpoint advances minRecoveryPoint to the end of that CHECKPOINT record. And the following replay doesn't advance minRecoveryPoint, it's assumed that flushing the buffers will do that as a side-effect. But no-op records replayed after the CHECKPOINT (such as RESTORE_POINT) do not dirty any pages, so the minRecoveryPoint is not updated as expected. As a result, minRecoveryPoint in pg_control ends up behind the actual replay position. This does not cause a recovery correctness issue, however the inaccurate pg_controldata "Minimum recovery ending location" prevents users or tools from using this value to verify that recovery has reached a specific restore point. Fix by reading the current replay position from shared memory and advancing minRecoveryPoint to match it. Since the replay position is always at least as far as the checkpoint end, this also subsumes the previous lastCheckPointEndPtr update. Reproducer: CHECKPOINT; SELECT pg_create_restore_point('test_rp'); -- recover with recovery_target_name + recovery_target_action=shutdown -- pg_controldata shows minRecoveryPoint 104 bytes behind --- src/backend/access/transam/xlog.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 2c1c6f88b74..ff9e373c4fa 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7721,7 +7721,6 @@ bool CreateRestartPoint(int flags) { XLogRecPtr lastCheckPointRecPtr; - XLogRecPtr lastCheckPointEndPtr; CheckPoint lastCheckPoint; XLogRecPtr PriorRedoPtr; XLogRecPtr receivePtr; @@ -7737,7 +7736,6 @@ CreateRestartPoint(int flags) /* Get a local copy of the last safe checkpoint record. */ SpinLockAcquire(&XLogCtl->info_lck); lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr; - lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr; lastCheckPoint = XLogCtl->lastCheckPoint; SpinLockRelease(&XLogCtl->info_lck); @@ -7864,15 +7862,32 @@ CreateRestartPoint(int flags) */ if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY) { - if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr) + /* + * Advance minRecoveryPoint to at least the current replay + * position. Normally this happens as a side effect of + * flushing dirty buffers, but during a shutdown restartpoint + * there may be records between the checkpoint and the + * recovery target that didn't dirty any buffers (e.g. a + * RESTORE_POINT record). Without this, a shutdown triggered + * by recovery_target_action leaves minRecoveryPoint behind + * the actual replay position. + */ { - ControlFile->minRecoveryPoint = lastCheckPointEndPtr; - ControlFile->minRecoveryPointTLI = lastCheckPoint.ThisTimeLineID; + XLogRecPtr replayPtr; + TimeLineID replayTLI; - /* update local copy */ - LocalMinRecoveryPoint = ControlFile->minRecoveryPoint; - LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI; + replayPtr = GetCurrentReplayRecPtr(&replayTLI); + if (ControlFile->minRecoveryPoint < replayPtr) + { + ControlFile->minRecoveryPoint = replayPtr; + ControlFile->minRecoveryPointTLI = replayTLI; + } } + + /* update local copy */ + LocalMinRecoveryPoint = ControlFile->minRecoveryPoint; + LocalMinRecoveryPointTLI = ControlFile->minRecoveryPointTLI; + if (flags & CHECKPOINT_IS_SHUTDOWN) ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY; } -- 2.47.3 --rlqg/1ddaRuGTcZI--