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