Re: Hash index: stop registering pin-only bucket pages in WAL (remove REGBUF_NO_CHANGE)

From: Greg Burd <greg(at)burd(dot)me>
To: pgsql-hackers(at)postgresql(dot)org
Cc: amit(dot)kapila16(at)gmail(dot)com, greg(at)burd(dot)me, vignesh21(at)gmail(dot)com, pgsql-hackers(at)lists(dot)postgresql(dot)org, michael(at)paquier(dot)xyz, pgsql(at)j-davis(dot)com, exclusion(at)gmail(dot)com
Subject: Re: Hash index: stop registering pin-only bucket pages in WAL (remove REGBUF_NO_CHANGE)
Date: 2026-11-03 16:11:19
Message-ID: auoFGJQNn5SdmPrZ@floki
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Sat, 31 Oct 2026 17:02:34 +0530, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> +1. I also think this should be a master-only change helping us to
> remove the use of REGBUF_NO_CHANGE from hash indexes. Also, the below
> change to make it work on back-branches appears too hacky to me.

Thanks. Then the back branches stay on 27caf4ca5ae, and this series is
master only. The #if HASH_WAL_REGISTER_BUCKET_PAGE shim you quoted was
in Vignesh's REL_18 compatibility patch, and it is not part of this
series.

v4 is attached, rebased on current master (5681f0cfa5a). The only
change from v3 is formatting: pgperltidy rewraps a few lines in the new
TAP test. The C code is the same as in v3.

0001 Don't register pin-only primary bucket pages in hash WAL records
0002 Append the hash primary bucket block number to WAL records only
when needed (Vignesh; Amit's suggestion)
0003 Add a recovery test for the hash WAL pin-only bucket page fix
(co-authored with Vignesh)
0004 Remove REGBUF_NO_CHANGE

One point I'd like a reviewer to look at in 0001:

redo now reads a block the record does not register. The block number
is appended to the record's main data only when the primary bucket page
is not one of the pages the record changes. Redo takes the relation
from a block that is always registered (block 1 for DELETE and
MOVE_PAGE_CONTENTS, block 2 for SQUEEZE_PAGE), and reads the page with
RBM_NORMAL, so a missing page goes through the same invalid-page
tracking as when the page was registered.

The page is not modified, so it needs no full-page image and no LSN
update; the old code registered it with REGBUF_NO_IMAGE, so redo already
worked from the on-disk copy. Two consumers of block references stop
seeing it. Recovery prefetch is one, so redo may do one synchronous
read of the bucket page per record when the page isn't cached. The
other is tools that collect changed blocks from WAL, such as pg_rewind
and the WAL summarizer, and losing it there is harmless because the page
is not changed. FSM redo reads unregistered blocks the same way, and
nbtree's pin scan did until 9f83468b353.

Testing:

- meson test setup, regress, isolation, recovery, pg_waldump and the
hash module, with PG_TEST_EXTRA=wal_consistency_checking, all four
patches applied: 68 of 68 suites pass on both builds, including
061_hash_vacuum_insert_crc and 027_stream_regress. With 0001 applied
alone, the same suites minus isolation also pass (64 of 64), so 0001
can be committed on its own.

- Streaming-standby CRC reproducer: 8 sessions inserting and deleting on
a single-bucket index under aggressive autovacuum,
wal_consistency_checking = 'hash'. As a control I ran master with
27caf4ca5ae reverted: the standby stops on "incorrect resource manager
data checksum". With v4, which also has 0004's REGBUF_NO_CHANGE
removal and restored asserts, the standby caught up with no errors.

- Cleanup lock on the standby: a cursor is parked in the bucket's
overflow chain, then the primary vacuums so that every DELETE,
MOVE_PAGE_CONTENTS and SQUEEZE_PAGE record has the primary bucket page
unmodified (is_primary F). On both builds replay waits on
BufferCleanup until the cursor finishes, and the cursor sees all 2250
rows, the same as unpatched master.

- I also reran the deadlock check from my first message on this thread
against current master. Taking the primary bucket page lock in
_hash_freeovflpage() after the metapage is locked exclusive still
hangs VACUUM and a scan of a bucket being populated by an incomplete
split. Taking it before the metapage read does not. 0001 takes
neither lock; this is only why the series doesn't lock the page.

I think 0001-0003 are ready for a committer. 0004 can go in with them
or right after.

best.

-greg

Attachment Content-Type Size
v4-0001-Don-t-register-pin-only-primary-bucket-pages-in-h.patch text/plain 15.4 KB
v4-0004-Remove-REGBUF_NO_CHANGE.patch text/plain 5.2 KB
v4-0003-Add-a-recovery-test-for-the-hash-WAL-pin-only-buc.patch text/plain 11.4 KB
v4-0002-Append-the-hash-primary-bucket-block-number-to-WA.patch text/plain 13.3 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Jingtang Zhang 2026-11-03 16:14:35 Re: Stale hash entries when reusing an auxiliary resource owner
Previous Message Tomas Vondra 2026-11-03 16:02:28 Re: [PATCH] Fix segmentation fault caused by reentrancy in RI_Fkey_cascade_del (ri_triggers.c)