| From: | Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com> |
|---|---|
| To: | Daniel Gustafsson <daniel(at)yesql(dot)se> |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com> |
| Subject: | Re: Offline data checksum changes can cause incorrect checksum state on standbys |
| Date: | 2026-08-28 09:24:17 |
| Message-ID: | apFTwa68Qn0S0dIX@bdtpg |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi,
On Fri, Aug 28, 2026 at 08:53:38AM +0200, Daniel Gustafsson wrote:
> > On 28 Aug 2026, at 07:33, Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com> wrote:
>
> > Only looking at 0001 here, I've a few comments:
>
> Thanks, I've yet to dig into it completely but below are a few quick questions
> to help me along the way.
>
> > === 1
> >
> > @@ -9288,17 +9572,33 @@ xlog2_redo(XLogReaderState *record)
> >
> > SpinLockAcquire(&XLogCtl->info_lck);
> > XLogCtl->data_checksum_version = state.new_checksum_state;
> > + SetLocalDataChecksumState(state.new_checksum_state);
> > SpinLockRelease(&XLogCtl->info_lck);
> >
> > This applies every XLOG2_CHECKSUMS record encountered during recovery, even when
> > the same record was applied before.
> >
> > For example, a standby can replay the final "on" record and then stop cleanly
> > without advancing its restartpoint beyond that record. If checksums are subsequently
> > disabled offline, the next startup begins from the older restartpoint and replays
> > the same on record again, overriding the offline disable.
>
> Do you mean that checksums are disabled offline across the cluster on all
> nodes, or just on the standby?
Disabling checksums offline on the standby is sufficient although that is not the
intended procedure.
Disabling offline on both the primary and standby also produce the issue.
> > === 2
> >
>
> If this can happen then online checksums wouldn't work at all right?
You’re right, my previous explanation was not fully accurate.
The 0001-specific concern is that a checkpoint can capture
checkPoint.dataChecksumState as inprogress-on, then insert XLOG_CHECKPOINT_REDO
correctly carrying on. The delay protects the flush, but the earlier value remains
stale. The equality check then does not persist on, and recovery no longer adopts
it from the REDO record, so a crash before the following checkpoint completes can
resolve the state back to off.
> Have you been able to construct a repro (with injection points) where a
> REDO record after a CHECKSUM record carries the wrong state?
Not with an injection point, but you can repro that way:
In xlog.c add 3 sleeps (see repro.txt attached):
- In SetDataChecksumsOn() to hold the launcher at inprogress-on.
- In SetDataChecksumsOn() to park it at on before its own checkpoint.
- In CreateCheckPoint() sleep/spin until XLogCtl->data_checksum_version == on.
Then:
start a cluster with initdb --no-data-checksums
Run SELECT pg_enable_data_checksums()
Then within 60s run CHECKPOINT
Once the checkpoint completes (SHOW data_checksums = on but pg_controldata still shows version 3)
pkill -9 the cluster
restart
check SHOW data_checksums: it comes back off.
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
| Attachment | Content-Type | Size |
|---|---|---|
| repro.txt | text/plain | 2.0 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Jan Nidzwetzki | 2026-08-28 10:04:14 | Re: [PATCH] Add tests for src/backend/nodes/extensible.c |
| Previous Message | cca5507 | 2026-08-28 09:11:28 | Re: timeout value overflow in wait for lsn |