| From: | Daniel Gustafsson <daniel(at)yesql(dot)se> |
|---|---|
| To: | Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com> |
| 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 06:53:38 |
| Message-ID: | 6370C439-408D-40F6-B956-55DF19FFE41C@yesql.se |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
> 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?
> === 2
>
> + * checkPoint.dataChecksumState was sampled while holding the WAL insert
> + * locks, so it is the state in effect at the redo point.
> .
> .
> .
> + SpinLockAcquire(&XLogCtl->info_lck);
> + if (checkPoint.dataChecksumState == XLogCtl->data_checksum_version)
> + ControlFile->data_checksum_version = checkPoint.dataChecksumState;
> + SpinLockRelease(&XLogCtl->info_lck);
>
> I’m not sure the "state in effect at the redo point" is always correct. There is
> a window between inserting the checksum transition record and updating
> XLogCtl->data_checksum_version.
>
> XLOG2_CHECKSUMS(on) records the target state. The transition can therefore
> proceed as follows:
>
> 1. The current shared state is inprogress-on.
> 2. XLogChecksums() inserts XLOG2_CHECKSUMS(on) and releases its WAL insertion
> lock.
> 3. Before the shared state is updated to on, the checkpoint still reads
> inprogress-on and inserts XLOG_CHECKPOINT_REDO.
> 4. The transition then updates the shared state to on.
>
> The WAL order is then:
>
> XLOG2_CHECKSUMS(on)
> XLOG_CHECKPOINT_REDO(inprogress-on)
>
> If the server crashes after the concurrent checkpoint from step 3 completes,
> but before the enabling operation’s later checkpoint completes, recovery starts
> from that redo point and does not replay the preceding on record. It can
> therefore resolve inprogress-on back to off. The equality check above does
> not repair this ordering.
If this can happen then online checksums wouldn't work at all right? This
window is happening inside a critical section while DELAY_CHKPT_START is set to
prevent a checkpoint from storing the state and completing to protect against
this. Have you been able to construct a repro (with injection points) where a
REDO record after a CHECKSUM record carries the wrong state?
--
Daniel Gustafsson
| From | Date | Subject | |
|---|---|---|---|
| Previous Message | vignesh C | 2026-08-28 06:50:03 | Re: Logical replication can lose an update after concurrent index invalidation |