GIN page deletion and page recycling bugs

From: Peter Geoghegan <pg(at)bowt(dot)ie>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: GIN page deletion and page recycling bugs
Date: 2026-08-19 22:59:21
Message-ID: CAH2-Wz=sKJcn+OtfVN9rdg+Ps9e4cuQWNP-9t12UE2d8nEG90Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I had Opus 5 look for more bugs in GIN. It found and diagnosed another
2. I attach 2 patches, each adding a test case that demonstrates a
distinct bug in GIN.

The first bug is an oversight in posting tree page deletion. The issue
is that ginScanPostingTreeToDelete fails to consider whether a target
page (or its left sibling page) is GinPageIsIncompleteSplit-marked.
Page deletion must not proceed if either page is marked, because the
right half of an unfinished split has no downlink yet, which deletion
is fundamentally incapable of handling. Currently, unsafe page
deletions are allowed, which leaves the posting tree in an
inconsistent state. This index corruption can lead to wrong answers,
which the test case added by 0001 demonstrates directly.

nbtree page deletion deals with the same incomplete split problem by
backing out of deleting the page. Fixing this bug will likely involve
teaching GIN to do much the same thing. ginScanPostingTreeToDelete
already avoids deleting both the leftmost and rightmost page; it
likely needs some additional deletion-is-unsafe tests. Incomplete
splits are rare, so we can reasonably assume an inserter will complete
them eventually (again, like nbtree).

The second bug is in page recycling. Apparently, GIN doesn't write a
WAL record to create a recovery conflict on standbys when a deleted
page is subsequently recycled on the primary. Both nbtree and GiST
already handle this correctly. It's intuitively obvious that GIN
should do the same thing, but the tap test added by 0002 actually
proves it: it demonstrates a query running on a standby that gets a
wrong answer (one that disagrees with the answer the same query gets
when a sequential scan is forced).

--
Peter Geoghegan

Attachment Content-Type Size
0001-Add-repro-GIN-VACUUM-unlinks-a-live-page-past-an-unf.patch application/octet-stream 11.3 KB
0002-Add-repro-GIN-page-reuse-raises-no-recovery-conflict.patch application/octet-stream 9.3 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Michael Paquier 2026-08-19 23:18:02 Re: test_aio: Fix broken error recovery assertions in 001_aio
Previous Message Melanie Plageman 2026-08-19 22:54:55 Re: Checkpointer write combining