Follow-up to #4926 (fixed in #5052).
The equal-version WAL re-apply added in #5052 repairs a torn 64KB page write, but only for the NEWEST version's delta region. Async flush coalesces several committed versions into a single physical page write, so a page can go v1(on-disk) -> v2 -> v3 -> v4 with only the v4 flush reaching the platter. If that flush tears, recovery re-applies v4's delta (version == disk) but skips v2 and v3 as strictly-older, so regions changed by v2/v3 can remain torn -> still silently corrupt.
The version header alone cannot distinguish a torn page from an intact one, so detecting which pages need the older deltas re-applied requires a per-page checksum (the longer-term fix already noted in #4926). An unconditional in-order replay of every WAL entry whose version <= disk version would also repair it, but changes the recovery semantics that also govern the version-gap / forceApply (replication) paths, so it needs its own careful design + tests.
Scope for this issue: add a per-page checksum written on flush and verified on recovery; on mismatch, replay the full WAL delta chain for that page from the last known-good version. Surfaced by the code review on #5052.
Follow-up to #4926 (fixed in #5052).
The equal-version WAL re-apply added in #5052 repairs a torn 64KB page write, but only for the NEWEST version's delta region. Async flush coalesces several committed versions into a single physical page write, so a page can go v1(on-disk) -> v2 -> v3 -> v4 with only the v4 flush reaching the platter. If that flush tears, recovery re-applies v4's delta (version == disk) but skips v2 and v3 as strictly-older, so regions changed by v2/v3 can remain torn -> still silently corrupt.
The version header alone cannot distinguish a torn page from an intact one, so detecting which pages need the older deltas re-applied requires a per-page checksum (the longer-term fix already noted in #4926). An unconditional in-order replay of every WAL entry whose version <= disk version would also repair it, but changes the recovery semantics that also govern the version-gap / forceApply (replication) paths, so it needs its own careful design + tests.
Scope for this issue: add a per-page checksum written on flush and verified on recovery; on mismatch, replay the full WAL delta chain for that page from the last known-good version. Surfaced by the code review on #5052.