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 <[email protected]>
Reported-by: Nikolay Samokhvalov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
Backpatch-through: 19

Branch
------
REL_19_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/268958a2e5feac370844e164a4e7e2535f6d2bc7

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(-)

Reply via email to