Re: Reduce WAL volume for heap tuple hint bits

From: Andrey Borodin <x4mmm(at)yandex-team(dot)ru>
To: Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com>
Cc: pgsql-hackers mailing list <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Reduce WAL volume for heap tuple hint bits
Date: 2026-08-19 16:07:55
Message-ID: 0D1EBC9D-5546-4E2C-889E-124B681E7EC5@yandex-team.ru
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On 17 Aug 2026, at 16:53, Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com> wrote:

Hi Matthias, Surya, Ewan,

Surya's reply appears to have been threaded under "Compression of bigger
WAL records", probably because of a stale References header. I am
bringing that part of the discussion back to the hint-bit thread here.

Thank you for the reviews. I think they expose two separate questions
that I had mixed together in v1: protection against page damage and
propagation of hint bits to standbys.

First, I agree with Matthias that the failure mode is broader than a
write containing some sectors from the old page and some from the new
page. An interrupted page write may leave bytes that belong to neither
version. A record containing only tuple offsets and hint bits cannot
repair such damage.

PostgreSQL already permits a clean page to be dirtied by a hint-only
change without an FPI when full_page_writes is on but wal_log_hints and
checksums are both off. That does not make it a good model to extend.
We should not use an existing hole in the protection as a reason to
design a better replicated /dev/null.

Surya wrote that the compact record should advance the page LSN so that
FlushBuffer() flushes the WAL before the page. I deliberately avoided
that, although the reason was not explained clearly enough in v1.

For a non-critical hint change, writing the page before the WAL record
is harmless by itself:

* if the page reaches disk first, the hint is already present;
* if the WAL record reaches disk first, redo can apply the hint;
* if neither reaches disk, the hint is lost and can be recomputed.

PostgreSQL already allows the first case when it sets hints without WAL.
Thus, an on-disk hint without a corresponding durable WAL record is not
by itself a violation of the WAL rule for critical data.

Advancing the page LSN would create a different problem. A later
ordinary modification could see an LSN newer than the checkpoint redo
pointer and conclude that the page was already protected by an FPI.
The compact hint record is not such protection, so that could leave the
ordinary modification exposed to page damage. I do not think we can
use PageSetLSN() for this record without separating the WAL-before-data
LSN from the LSN used to decide whether an FPI is required.

There is, however, a potentially useful and much narrower purpose for
the record. With full_page_writes off, PostgreSQL still emits an
XLOG_FPI_FOR_HINT record, but it contains only a block reference and its
redo is a no-op. It does not propagate the hint bits to a standby.

As I understand the standby side, it may compute the hints itself while
reading the page. However, when wal_log_hints or checksums require hint
WAL, recovery cannot write a new WAL record and therefore does not dirty
an otherwise clean page. The locally computed hints then remain only
in memory and can disappear on eviction. Please correct me if I am
missing another path that persists them.

This suggests reclassifying the proposal. Instead of reducing WAL by
replacing an FPI, it could deliver heap visibility hints with
wal_log_hints on, full_page_writes off, and checksums disabled.
In that configuration the compact record will usually be larger than
today's block-reference-only FPI_FOR_HINT record, so WAL reduction is no
longer present. The benefit would be that the standby receives and
can persist the hints selected by the primary.

Matthias, Surya, Ewan, do you think that is a useful and sound scope for
the patch? It seems very narrow, so we can just rejection the patch.

Ewan, thank you for suggesting that the new record use an existing
resource manager. I have prepared a version that moves it to Heap2 as
XLOG_HEAP2_HINT_BITS. I am not attaching it yet because I think we
should agree on the design and the actual purpose of the patch first.

Best regards, Andrey Borodin.

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Corey Huinker 2026-08-19 17:15:13 Re: use of SPI by postgresImportForeignStatistics
Previous Message Grigorev Jurij 2026-08-19 15:59:04 [PATCH] JIT inlining SIGSEGV in MemoryBuffer::getFile with LLVM 17 / GCC 13