Support shared-lock upgrade in foreign key check
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Summary
When `tidb_foreign_key_check_in_shared_lock` is enabled, a transaction that:
1. inserts or updates a child row that references a parent row, and then
2. updates that same parent row in the same transaction
fails with:
```text
ERROR 1105 (HY000): upgrading a shared lock to an exclusive lock is not supported
```
This makes a common foreign-key workflow fail even when the parent row update does not modify the referenced key column.
## Describe the solution you'd like
Support this transaction pattern when foreign-key shared-lock checking is enabled.
## Describe alternatives you've considered
- Disable `tidb_foreign_key_check_in_shared_lock`
- This avoids the failure, but it also changes the locking behavior and is not a real fix.
- Split the logic into multiple transactions
- This is a workaround, but it changes application semantics and is not always acceptable.
- Reorder application SQL
- In some flows this is hard or impossible once the child insert and parent update are both required in one atomic transaction.
## Minimal reproduction
Note: reproduction requires `tidb_foreign_key_check_in_shared_lock` to be enabled in the reproducing session.
```sql
DROP DATABASE IF EXISTS fk_issue_repro;
CREATE DATABASE fk_issue_repro;
USE fk_issue_repro;
CREATE TABLE parent (
id BIGINT PRIMARY KEY,
v BIGINT NOT NULL
);
CREATE TABLE child (
id BIGINT PRIMARY KEY,
parent_id BIGINT NOT NULL,
CONSTRAINT fk_child_parent FOREIGN KEY (parent_id) REFERENCES parent(id)
);
INSERT INTO parent VALUES (1, 0);
SET SESSION tidb_foreign_key_check_in_shared_lock = 1;
START TRANSACTION;
INSERT INTO child VALUES (1, 1);
UPDATE parent SET v = v + 1 WHERE id = 1;
COMMIT;
```
## Actual behavior
The `UPDATE parent ...` statement fails with:
```text
ERROR 1105 (HY000): upgrading a shared lock to an exclusive lock is not supported
```
## Expected behavior
The transaction should commit successfully. Updating a non-key column on the parent row after the child row passes FK checking should be supported in the same transaction.
## Additional context
- Verified locally against `8.0.11-TiDB-v8.5.6`
- Verified that the same SQL succeeds when `SET SESSION tidb_foreign_key_check_in_shared_lock = 0`
Contributor guide
Assessment
This issue has not been assessed yet.