On 14/12/2024 01:44, Andres Freund wrote:
The zero_damaged_pages path in bufmgr.c makes sense to me, but this one seems
less sane to me. If you want to recover from a data corruption event and
can't dump the data because a seqscan stumbles over an invalid page -
zero_damaged_pages makes sense.
Seqscans or tidscans won't reach the mdreadv() path, because they check the
relation size first. Which leaves access from indexes - e.g. an index pointer
beyond the end of the heap. But in that case it's not sane to use
zero_damaged_pages, because that's almost a guarantee for worsening corruption
in the future, because the now empty heap page will eventually be filled with
new tuples, which now will be pointed to by index entries pointing that were
created before the zeroing.
Well, if you need to do zero_damage_pages=off, you're screwed already,
so I don't know think the worsening corruption argument matters much.
And you have the same problem by pages zeroed by a seqscan too. To avoid
that, you'd want to mark the page explicitly as "damaged, do not reuse"
rather than just zero it, but that'd be a lot of new code.
Hmm, looking at index_fetch_heap(), I'm surprised it doesn't throw an
error or even a warning if the heap tuple isn't found. That would seem
like a useful sanity check. An index tuple should never point to a
non-existent heap TID I believe.
I'm wondering if we should just put an error into the relevant paths in HEAD
and see whether it triggers for anybody in the next months. Having all these
untested paths in md.c forever doesn't seem great.
+1
--
Heikki Linnakangas
Neon (https://neon.tech)