mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Say in the FSM README why its hint writes still need full page images
The Recovery section said we would "operate correctly without the full page
images that MarkBufferDirtyHint() provides", offering them only as a way to
lose less slot knowledge to RBM_ZERO_ON_ERROR. That is true of freespace.c,
which passes RBM_ZERO_ON_ERROR on every read, and false of the system around
it, which reads the same files and does verify checksums. Reading it as a
licence to dirty FSM pages without a full page image is what led to
c06d1a4ba6, since reverted.
Say instead that RBM_ZERO_ON_ERROR is a property of this directory rather
than of the fork, and name the readers that do not share it:
RelationCopyStorage(), RelationCopyStorageUsingBuffer(), base backups and
pg_checksums. Rather than presenting today's behavior as the only one
possible, note that the alternative is for all of that code to skip checksum
validation of the FSM.
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://postgr.es/m/20260901211837.f6.noahmisch%40microsoft.com
This commit is contained in:
@@ -189,9 +189,25 @@ to propagate the new free-space info into the upper pages of the FSM tree.
|
||||
As a result when we write to the FSM we treat that as a hint and thus use
|
||||
MarkBufferDirtyHint() rather than MarkBufferDirty(). Every read here uses
|
||||
RBM_ZERO_ON_ERROR to bypass checksum mismatches and other verification
|
||||
failures. We'd operate correctly without the full page images that
|
||||
MarkBufferDirtyHint() provides, but they do decrease the chance of losing slot
|
||||
knowledge to RBM_ZERO_ON_ERROR.
|
||||
failures.
|
||||
|
||||
That RBM_ZERO_ON_ERROR is a property of this directory, not of the FSM fork
|
||||
itself. The files themselves are ordinary relation files, and plenty of code
|
||||
outside freespace.c reads them and does verify checksums:
|
||||
RelationCopyStorage(), which ALTER TABLE ... SET TABLESPACE runs over every
|
||||
fork; the read stream in RelationCopyStorageUsingBuffer(), used by
|
||||
CREATE DATABASE ... STRATEGY = wal_log; and the checksum verification in base
|
||||
backups and in pg_checksums. The alternative would be all such code skipping
|
||||
checksum validation of *_fsm files, and that may be the right call someday.
|
||||
Today they do verify, so what we write here has to be valid.
|
||||
|
||||
So the full page images MarkBufferDirtyHint() writes are not just an
|
||||
optimization that reduces how often RBM_ZERO_ON_ERROR loses knowledge.
|
||||
When checksums or wal_log_hints are enabled they are what keeps an FSM page
|
||||
that reaches disk either checksum-valid or repairable by a later FPI. Do not
|
||||
replace MarkBufferDirtyHint() with MarkBufferDirty() here on the grounds that
|
||||
the FSM survives torn pages; it does, but the rest of the system is not
|
||||
promised the same.
|
||||
|
||||
Relation extension is not WAL-logged. Hence, after WAL replay, an on-disk FSM
|
||||
slot may indicate free space in PageIsNew() blocks that never reached disk.
|
||||
|
||||
Reference in New Issue
Block a user