Skip to content

crosscluster/logical: transactional LDR skips unique-constraint lock on DELETE when UC columns ⊆ PK #172367

Description

@jeffswenson

Describe the problem

In transactional LDR lock derivation, deriveUniqueLocks applies the
"values unchanged" skip (uc.equal(Row, PrevRow)) unconditionally, while
deriveFKLocks guards the same skip with row.IsUpdateRow(). For a DELETE,
Row is decoded from the key, so the PK columns are populated. If a unique
constraint's columns are all PK columns — e.g. PRIMARY KEY (a, b), UNIQUE (a)
— then Row and PrevRow agree on the UC columns, the skip fires, and no
unique lock is emitted for the value the delete releases.

Impact

Source serializes T1 DELETE (a=1,b=2) before T2 INSERT (a=1,b=3) via
UNIQUE(a). On the destination the lock sets don't overlap
(T1={PK(1,2)}, T2={PK(1,3), UC(1)}), so the scheduler may apply T2 before T1
→ duplicate-key error → DLQ/pause. The intra-txn topological sort has the same
hole (edges only follow shared lock hashes).

Code references

Suggested fix

Guard the equality skip with row.IsUpdateRow(), mirroring the FK path.

Epic CRDB-65552

Jira issue: CRDB-65602

Metadata

Metadata

Assignees

Labels

A-cdcChange Data CaptureA-logical-data-replicationC-bugCode not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior.O-agentFiled by an AI agent; usually the result of a human/agent investigation sessionT-cdc

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions