| From: | Yao Feng <fengyao0087(at)gmail(dot)com> |
|---|---|
| To: | Salma El-Sayed <salmasayed182003(at)gmail(dot)com> |
| Cc: | pgsql-hackers(at)postgresql(dot)org |
| Subject: | Re: [GSoC 2026] - B-tree Index Bloat Reduction - Approach & Questions |
| Date: | 2026-09-22 11:49:00 |
| Message-ID: | CAAU0Mh0k3ay2AYQagxXtF4Ofx_EAHfAf5-GpxG2h4gNKz_mwCA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi Salma,
While testing v3, I noticed a crash in _bt_killitems() triggered by
concurrent bt_merge().
The problem
-----------
An index scan reads leaf page L, drops its content lock (keeping the
pin), and visits the heap. Finding dead tuples, it records them in
so->killedItems[]. Concurrently, bt_merge() acquires BT_WRITE on L,
moves all tuples to R, and calls BTPageSetMergedAway(), which sets
pd_lower to 32 and marks L as BTP_MERGED_AWAY.
When the scanner calls _bt_killitems() in !so->dropPin mode, it
re-acquires BT_READ and proceeds without checking page flags.
PageGetMaxOffsetNumber() returns (32 - 24) / 4 = 2, because the
8-byte safemergexid at bytes 24..31 overlaps with pd_linp[0..1].
The function then interprets safemergexid bits as ItemIdData, causing
Assert(ItemIdHasStorage) failures in debug builds or SIGSEGV in
production.
The so->dropPin path is not affected -- it checks LSN first and gives
up if the page was modified. The !so->dropPin path assumes the pin
keeps page contents stable, which holds for standard VACUUM (cleanup
lock required) but not for bt_merge() (regular BT_WRITE by design).
Proposed fix
------------
Add a check for P_ISMERGEDAWAY after acquiring the lock:
+ /*
+ * bt_merge() can convert a page to BTP_MERGED_AWAY while we hold a
+ * pin but no lock. The original tuples are gone; give up on hinting.
+ */
+ if (P_ISMERGEDAWAY(opaque))
+ goto unlock_page;
Abandoning LP_DEAD hints is harmless -- a subsequent VACUUM will clean
up the dead tuples.
Any thoughts on this?
Best regards,
Yao Feng
| Attachment | Content-Type | Size |
|---|---|---|
| 0002-test-injection-point.patch | application/x-patch | 696 bytes |
| test_killitems_crash.sh | application/x-sh | 4.0 KB |
| 0001-nbtree-Guard-_bt_killitems-against-concurrent-page-m.patch | application/x-patch | 1.0 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Etsuro Fujita | 2026-09-22 11:50:46 | Re: Several issues with postgres_fdw stats import |
| Previous Message | Etsuro Fujita | 2026-09-22 11:38:52 | Re: Several issues with postgres_fdw stats import |