From 87e27cd71b3267be7869f342dc41d09373b23242 Mon Sep 17 00:00:00 2001 From: shihao zhong Date: Tue, 20 Oct 2026 21:53:23 -0400 Subject: [PATCH v1 1/2] Always WAL-log the VM page changed by truncation visibilitymap_prepare_truncate() clears bits in the last remaining visibility map page, but logged that page only when hint bits are WAL-logged. Without that, an incremental backup misses the change and the restored cluster keeps stale all-visible bits. Backpatch-through: 17 --- src/backend/access/heap/visibilitymap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c index fe5ce437e1b..652d3ad315b 100644 --- a/src/backend/access/heap/visibilitymap.c +++ b/src/backend/access/heap/visibilitymap.c @@ -519,14 +519,15 @@ visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks) /* * Truncation of a relation is WAL-logged at a higher-level, and we - * will be called at WAL replay. But if checksums are enabled, we need - * to still write a WAL record to protect against a torn page, if the - * page is flushed to disk before the truncation WAL record. We cannot - * use MarkBufferDirtyHint here, because that will not dirty the page - * during recovery. + * will be called at WAL replay. But the truncation WAL record does + * not reference this page, so we still log it here. WAL summaries + * for incremental backup need that, and so does torn page protection + * if the page is flushed to disk before the truncation WAL record. We + * cannot use MarkBufferDirtyHint here, because that will not dirty + * the page during recovery. */ MarkBufferDirty(mapBuffer); - if (!InRecovery && RelationNeedsWAL(rel) && XLogHintBitIsNeeded()) + if (!InRecovery && RelationNeedsWAL(rel)) log_newpage_buffer(mapBuffer, false); END_CRIT_SECTION(); -- 2.37.1 (Apple Git-137.1)