[WIP] Adding a { LOCK ROWS | LOCK KEY INDEX } clause to FK definitions

From: Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: [WIP] Adding a { LOCK ROWS | LOCK KEY INDEX } clause to FK definitions
Date: 2026-06-22 12:50:34
Message-ID: CAEze2WjPFFfgtWyd8Cfago9fpXd-RKh_Ai6knFdHFztmfXMucw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

When a base (fact) table is frequently referenced in a system with
sufficiently high insertion/update rate on the FK referencing side,
the mxact churn of FKs' RI-based row locks can become a big issue,
even when a row's key values never gets updated. The new SLRU GUCs
can help allow users avoid the performance penalty by keeping more of
the SLRUs in memory, but it doesn't fix the underlying problem.

Attached is a patch that implements a second FK locking scheme, which
uses heavyweight locks to guarantee that the relevant rows live for at
least until we commit. In this new scheme, to update or remove key
values in the base (referenced) table, the session must now take a
SHARE ROW EXCLUSIVE lock on the index that backs the FK relation.
Insertions and updates into the referencing table (the one with the
FK) will take a ROW EXCLUSIVE lock on that same index to make sure no
key values are being removed from the table while their transactions
are still ongoing.

The lock levels were chosen to minimize the cost of insertions into
the referencing table, whilst also avoiding lock conflicts where
possible. I'm open to suggestions to improve this further, though I
think the current levels are about as good as it's gonna get; the base
table key update needs a lock that conflicts with as few possible lock
levels for unrelated DML, and the referencing table's RI checks need
the lowest lock level that conflicts with that lock.

-=-=-=-=-=-=-=-=-

Work in progress:

The atttached patchset has one known issue that I'm not 100% sure
about if it's really an issue:
The test I adjusted from fk-concurrent-pk-update.spec to make sure FKs
behave correctly in LOCK KEY INDEX mode currently fails to cause
serialization conflicts for SSI transactions. I assume that is because
the new locking regime provides some easier-to-linearize data
accesses, but I'd greatly appreciate someone else's eyes on this to
make sure that (1) the test failure [ no serialization issues detected
] is expected, and that (2) I didn't miss any other visibility-related
isues.

Another work in progress is the exact syntax: I personally think that
the proposed { LOCK ROWS | LOCK KEY INDEX } naming is a good
descriptive syntax, but I'm open to improvements. Something which I've
done without much careful thought is where the LOCK clause was added
in the syntax; I found it to fit most naturally just behind the
reference clause (ahead of the MATCH clause), but am open to adjusting
the positioning too to avoid interleaving the standard's clauses with
our extensions to the standard.

Kind regards,

Matthias van de Meent
Databricks (https://www.databricks.com)

Attachment Content-Type Size
v1-0001-FK-RI-Add-heavy-weight-locking-option-for-RI-chec.patch application/octet-stream 41.3 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Tatsuo Ishii 2026-06-22 12:55:36 Re: Row pattern recognition
Previous Message Ewan Young 2026-06-22 12:49:54 Re: REPACK CONCURRENTLY fails on tables with generated columns