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

From: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>
To: 'Greg Burd' <greg(at)burd(dot)me>, vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, shihao zhong <zhong950419(at)gmail(dot)com>, Michael Paquier <michael(at)paquier(dot)xyz>, Jeff Davis <pgsql(at)j-davis(dot)com>, Alexander Lakhin <exclusion(at)gmail(dot)com>, "pgsql-hackers(at)lists(dot)postgresql(dot)org" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Hash index: stop registering pin-only bucket pages in WAL (remove REGBUF_NO_CHANGE)
Date: 2026-11-13 10:21:27
Message-ID: OS7PR01MB1831738CC51177B1392E379DBF57F2@OS7PR01MB18317.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

Thanks for updating the patch. Few more comments. Note that I did not review 0003,
because I was not sure it's intended to be pushed.

01.
```
+ * If buf is an overflow page, the primary bucket page is not
+ * changed and we hold only a pin on it, so it is not
+ * registered. Append its block number instead, and replay
+ * takes a cleanup lock on it. It is not needed otherwise
```

I think we should clarify why the primary bucket itself or block number should be
registered. Idea:

```
/*
* Replay must take a cleanup lock on the primary bucket page to
* serialize with scans on a hot standby. If buf is an overflow
* page, the unchanged primary page is held only by a pin, so append
* its block number instead of registering it. Otherwise block 0
* identifies the primary page.
*/
```

02.
```
+/*
+ * Take a cleanup lock on the primary bucket page of the bucket that a
+ * squeeze or delete record operates on, when that page is not one of the
+ * pages the record changes and so is not registered in it. Its block number
+ * is stored in the main data of the record, right after the fixed-size struct
+ * of rec_size bytes.
+ *
+ * This serializes replay against scans on a hot standby, which pin the
+ * primary bucket page for their whole duration; see the comments in the
+ * callers. The page is not modified, so nothing is done with it besides
+ * locking it. block_id must be a block of the same index registered in
+ * the record.
+ */
+static Buffer
+hash_xlog_lock_primary_bucket(XLogReaderState *record, uint8 block_id, Size rec_size)
```

In contrast this might be too detail, the user of the function might not need
such an info. How about:

```
/*
* Take a cleanup lock on an unregistered primary bucket page, whose
* block number is stored in the record's main data. This serializes
* replay against scans on a hot standby. block_id must identify a
* registered block of the same index.
*/
```

03.
```
+ * Register only the pages this record changes. The primary bucket
+ * page is registered only if it is the write page and is modified;
+ * otherwise we may hold only a pin on it, so append its block number
+ * and replay takes a cleanup lock on it.
```

Same as 01, we can clarify the reason why the primary bucket is needed. Idea:

```
/*
* Replay needs the primary bucket block number to acquire a cleanup
* lock. Register it as block 0 when it is modified; otherwise append
* its block number to the record.
*/
```

Best regards,
Hayato Kuroda
FUJITSU LIMITED

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Jan Nidzwetzki 2026-11-13 10:31:05 Re: Prevent object capture in CREATE/ALTER EXTENSION scripts
Previous Message Daniel Gustafsson 2026-11-13 10:07:24 Re: ISBN range table