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 1x1K10-0057Fh-0e for pgsql-hackers@arkaria.postgresql.org; Tue, 01 Sep 2026 08:38: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 1x1K0z-005FPs-0S for pgsql-hackers@arkaria.postgresql.org; Tue, 01 Sep 2026 08:38:45 +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 1x1K0y-005FPk-2M for pgsql-hackers@lists.postgresql.org; Tue, 01 Sep 2026 08:38:44 +0000 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1x1K0w-00000003RQP-3zPq for pgsql-hackers@lists.postgresql.org; Tue, 01 Sep 2026 08:38:43 +0000 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-49b8687630fso32402835e9.3 for ; Tue, 01 Sep 2026 01:38:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788251921; x=1788856721; darn=lists.postgresql.org; h=in-reply-to:content-disposition:content-type:mime-version :references:message-id:subject:cc:to:from:date:from:to:cc:subject :date:message-id:reply-to:content-type; bh=zm/WApITSY7Ofv7/AsM8e85l/6Se6clad9w/RExBt0M=; b=cZWBpRb3tY6Fa81dXBxCsjpbnr3pFIlHmLxrVh/mSMiNxk2aQ4NXsTsvEk4U3/PH8r wR7/29Fkj8Jul+VhX0f1wUTlN2kNdGYeHUkdG/fRbfM0g9KaY0ZiILEn/NYAOqNV30+/ 9M1lejcfNgrvXniqSEevzn50XR3y1JBsSG3sGfSLiuzArDh4vDeKHF+CRe7poGp4E+Ok Ysf4J+sXwzXU2bWDcchv1Ho8M+NrqMwaEu9bG9PR6TlhrXrkXJzlIO9a4cAiVn4EvbmQ JQnSWGeSA6bb84eRN99C2xf7pkVp/gDXYSeL55ODMkhABMEfW57g586uQ6q0DumHxxtf jW+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788251921; x=1788856721; h=in-reply-to:content-disposition:content-type: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 :content-type; bh=zm/WApITSY7Ofv7/AsM8e85l/6Se6clad9w/RExBt0M=; b=a7PCVrKwXyA8xRfDqwgbS/VSZjcSSSKxKZy1D3Nxp01U0DkauLDYfEkbDN5+Rf42Al cdKFQC+/ULegR5yAVHYPRr7J+pG05J1eNFPCy89u1+mcr4YyBuhkKix517+bwmtrpeh1 lhUo+5bhUq5t0IEPHyJXFx3MaCXsxhRVpWvBMGuEIc0ZNGqUSpBILtQddtC3Ro4cdha1 N/vUE6iZPte9f51VjMNFC8hXdVRHsyjBoWkOzLyf5XCaZ5YE5rPk0kwzuwJbNiPQqV8J GX7vwx4kx3f1i/2PcZXXgIJfg3i3JwLLPviAuo87w6wUWIl7t2Nif/PxxB8pR9lxCpJk B2Nw== X-Forwarded-Encrypted: i=1; AHgh+RofwY7asOh+vnN54Q9uAWetjQC4AE86jIflLLoXSifyRYqVsKYXibW1aaQO/pAdGQq+Xy9C4BS+GFg4770f@lists.postgresql.org X-Gm-Message-State: AFuF++lHmc8gc7bIWojDvMX2KggxTo1LDWfrg/mCkL68HXz0fwZ3NlAP FZz6L76QCvvycHg6Q2Lotu9ZXcYMUDK2JOfibDLTz74ZU64HcQ4ETNnO X-Gm-Gg: AR+sD10oug38KIdxpTEiY/iPAM+F3uFARqC6HFkQV6YxEOUy+GVxYCvoMR5s8iXZPwa hn5C1X3hu1vTqEM9Shl6Dow+bvSeJgWwLw7BKe+9yvVy5GJxnhXCWEYhLPxVHC8yd5lcCjarchd AdGiJKMq4VW8Mk7gYsMLmNSnS9nd2L56dHmYzp8mG7LQGzgTTz9PZ2HauaYfG7d2HdoYveuZhOh a9LjRuyJ2TKSlUwDalVVGSgrD9nMOcwlKY09SJYZzltgxfMRaHH2d1oSRF3VP88+cEB2or7aye2 HJCrEEU3eDTW07BdBTAOoqj1G1hFhUqBQM/6NQ33H4/G1DxEvilkdyu4wo+8pDRIZSLBF/FgmFC Gm9R6/dQB7AIkT/LYCiYPyYM4MejZQoskzJWEXCzX2KxEOsDHKMt7ydVuFGmzw2KqS8eYu9jMqU GHRP65FvZU1OHETlBMr7Lq7avB8tkt5f32R8ekdORoYfOdWFuoQDPPeNohe6AD9bvg9ZnqEuhHP vaFlgivab4qtro/yCg4eEbv1a/fpn++xFbw2mNbjhhRtqGK X-Received: by 2002:a05:600c:530e:b0:49c:de80:b833 with SMTP id 5b1f17b1804b1-49cde80b8b8mr61004385e9.2.1788251920059; Tue, 01 Sep 2026 01:38:40 -0700 (PDT) Received: from bdtpg (ec2-15-237-197-144.eu-west-3.compute.amazonaws.com. [15.237.197.144]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cdd73f7a4sm43735985e9.12.2026.09.01.01.38.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Sep 2026 01:38:39 -0700 (PDT) Date: Tue, 1 Sep 2026 08:38:38 +0000 From: Bertrand Drouvot To: Zsolt Parragi Cc: Daniel Gustafsson , pgsql-hackers@lists.postgresql.org Subject: Re: Offline data checksum changes can cause incorrect checksum state on standbys Message-ID: References: <8DCA12FF-0199-403D-A203-666528A25DB6@yesql.se> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="gk2ldDDifaa2RZdE" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --gk2ldDDifaa2RZdE Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, On Tue, Sep 01, 2026 at 12:31:42AM +0100, Zsolt Parragi wrote: > > I found a case where the source's online enable occurs after divergence and was > > never seen by the target, but replay skips it instead of applying it: > > .... > > Maybe the watermark needs timeline context, or pg_rewind needs to adjust it > > when it comes from the target's divergent history? > > Thanks! v8 adds the latter, with a new test case verifying this scenario. Thanks! As far the new test: === 1 +# Clean switchover back to A; enable checksums online on it. +$node_b->stop('fast'); +$node_a->promote; IIUC, the preceding wait_for_catchup() does not cover the shutdown checkpoint written by stop(). Therefore, the divergence checkpoint in scenario 2 is not guaranteed to carry off, as described. === 2 +enable_data_checksums($node_b, wait => 'on'); +test_checksum_state($node_b, 'on'); ... +$node_a->wait_for_catchup($node_b, 'replay', $node_a->lsn('insert')); +test_checksum_state($node_b, 'on'); The target is already "on" before pg_rewind, so the final assertion does not prove that the source's enable record was replayed. Please find attached a small patch addressing those two test comments to apply on top of v8. What do you think? === 3 + /* + * End of the newest XLOG2_CHECKSUMS record this node has written or + * applied. and + * would skip them as already applied. Clamp it to the divergence point, + * so that every transition record on the source's history takes effect. + */ + if (ControlFile_new.data_checksum_lsn > divergerec) + ControlFile_new.data_checksum_lsn = divergerec; divergerec is not necessarily the end of an XLOG2_CHECKSUMS record, so the comment no longer describes every value the field may contain. Maybe it should describe it as the WAL position through which checksum transitions are covered? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com --gk2ldDDifaa2RZdE Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v8-021-test-fixes.txt" diff --git a/src/test/modules/test_checksums/t/021_rewind_divergent_transitions.pl b/src/test/modules/test_checksums/t/021_rewind_divergent_transitions.pl --- a/src/test/modules/test_checksums/t/021_rewind_divergent_transitions.pl +++ b/src/test/modules/test_checksums/t/021_rewind_divergent_transitions.pl @@ -40,6 +40,19 @@ sub controldata_watermark return (hex($1) << 32) + hex($2); } +sub wait_for_shutdown_checkpoint_replay +{ + my ($primary, $standby) = @_; + my ($stdout) = run_command([ 'pg_controldata', $primary->data_dir ]); + $stdout =~ /^Latest checkpoint location:\s*([0-9A-F\/]+)$/m + or die "checkpoint location missing from pg_controldata output"; + my $shutdown_checkpoint = $1; + + $standby->poll_query_until('postgres', + "SELECT pg_last_wal_replay_lsn() > '$shutdown_checkpoint'::pg_lsn;") + or die "standby never replayed the shutdown checkpoint"; +} + # Old primary, checksums off. wal_log_hints is required by pg_rewind # on a cluster without data checksums. my $node_a = PostgreSQL::Test::Cluster->new('node_a'); @@ -63,6 +76,7 @@ $node_a->wait_for_catchup($node_b, 'replay', $node_a->lsn('insert')); # Clean switchover to B; enable checksums online on it. $node_a->stop('fast'); +wait_for_shutdown_checkpoint_replay($node_a, $node_b); $node_b->promote; enable_data_checksums($node_b, wait => 'on'); test_checksum_state($node_b, 'on'); @@ -123,9 +137,11 @@ test_checksum_state($node_a, 'off'); # Clean switchover back to A; enable checksums online on it. $node_b->stop('fast'); +wait_for_shutdown_checkpoint_replay($node_b, $node_a); $node_a->promote; enable_data_checksums($node_a, wait => 'on'); test_checksum_state($node_a, 'on'); +my $source_enable_watermark = controldata_watermark($node_a); # The old primary restarts on its old timeline and enables checksums # online independently: both control files say "on", the divergence @@ -162,6 +178,8 @@ is($node_b->safe_psql('postgres', "SELECT count(*) FROM t_div;"), '0', 'divergent insert was rewound'); $node_b->stop('fast'); +is(controldata_watermark($node_b), $source_enable_watermark, + 'rewound node replayed the source checksum transition'); command_ok([ 'pg_checksums', '--check', '-D', $node_b->data_dir ], 'checksums valid on the rewound node'); --gk2ldDDifaa2RZdE--