pg.ddx.io  pgsql-committers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Amit Langote <amitlan@postgresql.org>
To: pgsql-committers@lists.postgresql.org
Subject: pgsql: Track RI fast-path FK-check batches per subtransaction
Date: Sat, 22 Aug 2026 07:26:06 +0000
Message-ID: <E1wxg7B-00000001cXm-0S7m@gemulon.postgresql.org> (raw)

Track RI fast-path FK-check batches per subtransaction

Commit 4113873 confined RI fast-path batching to the top transaction
level to avoid mishandling the batch cache on subtransaction abort.
That disabled batching for a foreign-key load wrapped in a savepoint,
such as:

  BEGIN; SAVEPOINT s; COPY fk_table FROM ...

This was a surprising performance cliff and departed from the usual
per-subtransaction resource handling.

Track cache entries per subtransaction instead.  Add AtEOSubXact_RI(),
called from CommitSubTransaction() and AbortSubTransaction() after
ResourceOwnerRelease().  On abort, it removes only entries opened by
the ending subtransaction, whose resources have just been released,
while leaving entries opened by an outer level intact.  Thus, an inner
subtransaction abort during outer-level trigger firing does not
discard the outer statement's batch.  On commit, no matching entry is
expected because its batch should already have been flushed at
statement end.  Each entry records the subtransaction that opened its
resources.

After an abort, the remaining slot storage and per-entry flush contexts
are reclaimed when TopTransactionContext is reset at top-level
transaction end.

A fast-path batch is filled and flushed within a single trigger-firing
cycle, so every row added to an entry must come from the subtransaction
that created it.  AtEOSubXact_RI() relies on this invariant to identify
an aborting subtransaction's entries by the subid stamped at entry
creation.  Assert the invariant in ri_FastPathBatchAdd().

Add regression coverage for batching during nested firing inside a
subtransaction, both with different constraints and with the same
constraint at the inner and outer firing levels.

Reported-by: Noah Misch <noah@leadboat.com>
Reported-by: Nikolay Samokhvalov <nik@postgres.ai>
Discussion: https://postgr.es/m/20260705222115.be.noahmisch@microsoft.com
Backpatch-through: 19

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/e2c812f1475dc75ab6f8a39fb5696d8d32d05fa1

Modified Files
--------------
src/backend/access/transam/xact.c         |  2 +
src/backend/utils/adt/ri_triggers.c       | 94 ++++++++++++++++++++++++++++---
src/include/commands/trigger.h            |  2 +
src/test/regress/expected/foreign_key.out | 70 +++++++++++++++++++++++
src/test/regress/sql/foreign_key.sql      | 57 +++++++++++++++++++
5 files changed, 217 insertions(+), 8 deletions(-)



view thread (4+ messages)

Message-ID: <E1wxg7B-00000001cXm-0S7m@gemulon.postgresql.org>
Permalink:  ../E1wxg7B-00000001cXm-0S7m@gemulon.postgresql.org/
Also on:    postgresql.org/message-id/E1wxg7B-00000001cXm-0S7m@gemulon.postgresql.org

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-committers@postgresql.org
  Cc: amitlan@postgresql.org, pgsql-committers@lists.postgresql.org
  Subject: Re: pgsql: Track RI fast-path FK-check batches per subtransaction
  In-Reply-To: <E1wxg7B-00000001cXm-0S7m@gemulon.postgresql.org>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox