Revert RI fast-path batching from REL_19_STABLE

From: Amit Langote <amitlangote09(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Cc: rmt(at)lists(dot)postgresql(dot)org
Subject: Revert RI fast-path batching from REL_19_STABLE
Date: 2026-09-03 13:36:06
Message-ID: CA+HiwqEDcCSDoYTtoXH4Ta_BpGN+revMZSLLj6GRz2_5ybwE1g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

Attached is a two-patch series to remove batching from the RI fast
path in REL_19_STABLE, while retaining the per-row fast path. Batching
accumulates rows from successive foreign-key trigger invocations and
checks them together against the referenced index when the batch fills
or the trigger-firing cycle ends, instead of checking each row during
its trigger invocation. I plan to leave the batched implementation
unchanged in master for v20 development.

Given the concerns raised about shipping this code in v19 [1], I
reviewed the fixes made since feature freeze. The batching fixes are
considerably more concerning than those to the underlying per-row fast
path, because they have repeatedly had to address how a live batch of
pending checks interacts with trigger-firing cycles, subtransactions,
deferred constraints, and SET CONSTRAINTS, rather than merely
correcting isolated implementation errors. Missing one such
interaction can leave a foreign key check buffered and never
performed, allowing a violating row to be committed without an error.
That fix history, together with the two still-open batching-related
items, has persuaded me that the concerns about shipping the batching
code in v19 are justified.

0001 is the same patch I posted separately at:

https://postgr.es/m/CA+HiwqEhm+_=bs=2wavAJz-UqC+1KebD31++mapJQQGweE8iQQ@mail.gmail.com

It fixes a snapshot-ordering bug in the per-row path that must be
addressed before 0002 removes batching and makes ordinary DML use that
path. In READ COMMITTED, ri_FastPathCheck() could take its scan
snapshot before waiting to lock the referenced relation. A referenced
row committed during that wait would not be visible to the old
snapshot, causing a false foreign key violation. Batching currently
masks this problem because it opens and caches the relations before
taking the snapshot used for the batch. The SPI path likewise acquires
the referenced-relation lock before selecting the snapshot used for
the check.

0002 removes the batching layer, the per-batch RI cache, and the
after-trigger callback and subtransaction machinery added to manage
their lifetime. It restores the affected after-trigger code to its
pre-batching form.

0002 removes tests that exercise only the batching implementation and
its callback and cache lifetime machinery. It retains, and where
necessary adapts, tests that continue to exercise the underlying RI
cases through the per-row path, including ALTER TABLE validation,
scan-key construction, deferred checks, re-entrancy, and metadata
invalidation. This preserves useful regression coverage in v19 and
minimizes unnecessary divergence in test coverage, simplifying future
backpatching of test cases. When I first tested the batching removal,
the only failure among the retained tests was the injection-point test
that exposed the snapshot-ordering bug fixed by 0001.

The per-row path has also required fixes since feature freeze,
including the snapshot-ordering fix in 0001. So far, however, its fix
history has not shown the same pattern of complexity as the fixes
needed to manage the lifetime of batched checks. On that basis, I
propose retaining the per-row path in v19 while removing the batching
layer.

Thoughts on removing batching while retaining the per-row fast path in
v19, and on retaining batching in its current state in master for v20
development, would be welcome.

--
Thanks,
Amit Langote

[1] https://www.postgresql.org/message-id/CA%2BHiwqHLATwtsp7vHa5xUVw%3DsX16%2B%2BRt1QSEGE1wSYCqJd5p9Q%40mail.gmail.com

Attachment Content-Type Size
v1-0002-Remove-batching-from-RI-fast-path-checks.patch application/octet-stream 103.3 KB
v1-0001-Take-RI-fast-path-snapshot-after-locking-referenc.patch application/octet-stream 6.3 KB

Browse pgsql-hackers by date

  From Date Subject
Previous Message Nathan Bossart 2026-09-03 13:31:45 Re: SSI: ON CONFLICT DO SELECT takes no predicate lock on the returned row