Re: GIN page deletion and page recycling bugs

From: Andrey Borodin <x4mmm(at)yandex-team(dot)ru>
To: Peter Geoghegan <pg(at)bowt(dot)ie>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Alexander Korotkov <aekorotkov(at)gmail(dot)com>, Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Subject: Re: GIN page deletion and page recycling bugs
Date: 2026-08-22 10:34:11
Message-ID: A0D18FCC-9E2A-4BE2-92E4-A7BB1CBF110C@yandex-team.ru
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On 20 Aug 2026, at 20:52, Peter Geoghegan <pg(at)bowt(dot)ie> wrote:
>
> Attached patch fixes the bug as outlined. It would be good to get a
> GIN expert to review this.

Hi Peter,

I don't think I qualify as a GIN expert, but both bugs and the proposed
fixes seem fairly clear to me. PFA a three-patch version. The first
two patches are intended for backpatching; the third one is for master
only.

Your patch looks correct to me. It might be worth covering the
incomplete target page separately: the test currently covers deletion
after an incomplete left sibling. I would also avoid the
expected count of 39879. Comparing the index result with a sequential
scan would express the correctness property more directly and tie the
test less closely to the physical page layout. This already failed in
Linux Autoconf CI, which produced 36449 instead of 39879 [0].

In the longer term, a heap-all-indexed check for GIN in amcheck would
be a better oracle for bugs like this.

The second patch follows your back-branch proposal and emits
XLOG_GIST_PAGE_REUSE when GIN reuses a deleted page. The reproducer now
expects replay to cancel the standby scan. Without the fix I get 7860
rows from the GIN scan instead of 112338 from the sequential scan; with
the fix the recovery conflict is raised as expected.

The third patch addresses one related old issue on master. GIN still
stores its deletion horizon as a 32-bit XID. After about 2 billion XIDs
a deleted page can be considered non-recyclable for the following
2-billion-XID window. GiST and nbtree were changed to store full XIDs in
6655a7299d8 and e5d8a999030. I mentioned the same problem in GIN in 2019
[1], but apparently we never followed up. The new representation has a
page flag, so pg_upgraded indexes keep the old conservative behavior for
their old deleted pages. I do not propose this part for backpatching.

Thanks!

Best regards, Andrey Borodin.

[0] https://github.com/x4m/postgres_g/actions/runs/32563364088/job/97008437447
[1] https://www.postgresql.org/message-id/AFDDB5CC-CC41-4E73-AD92-09AF4BDE926F%40yandex-team.ru

Attachment Content-Type Size
v2-0001-Fix-GIN-VACUUM-unfinished-split-page-deletion-bug.patch application/octet-stream 11.8 KB
v2-0002-Raise-recovery-conflicts-when-recycling-GIN-pages.patch application/octet-stream 11.4 KB
v2-0003-Use-full-XIDs-in-deleted-GIN-posting-tree-pages.patch application/octet-stream 8.9 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Etsuro Fujita 2026-08-22 10:36:48 Re: use of SPI by postgresImportForeignStatistics
Previous Message Etsuro Fujita 2026-08-22 10:26:15 Re: Further cleanup related to statistics import support in postgres_fdw