cockroachdb / cockroachdb/cockroach

sql: SELECT FOR UPDATE does not prevent insertion of new rows (phantoms)

Open
#120,673 1 comment 0 reactions 0 assignees View on GitHub
A-read-committed C-enhancement docs-done docs-known-limitation T-kv
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

Regardless of isolation level, `SELECT FOR UPDATE` and `SELECT FOR SHARE` statements in CockroachDB do not prevent insertion of _new_ rows matching the search condition (a.k.a. phantoms). This is the same as PostgreSQL behavior at all isolation levels, but can be a little surprising.

Here's a demonstration:

```sql
CREATE TABLE ab (a INT PRIMARY KEY, b INT);
INSERT INTO ab VALUES (0, 0), (1, 1), (2, 2);

-- first connection: hold open a transaction with exclusive locks
BEGIN;
SELECT * FROM ab WHERE a > 0 FOR UPDATE;

-- second connection: these will not block, as expected
UPDATE ab SET b = b + 10 WHERE a = 0;
INSERT INTO ab VALUES (-1, -10);

-- third connection: this will block, as expected
UPDATE ab SET b = b + 10 WHERE a = 1;

-- fourth connection: these will *not* block, which matches PostgreSQL behavior but could be surprising
INSERT INTO ab VALUES (3, 30);
UPDATE ab SET a = a + 10 WHERE a = 0;
```

Other databases have different behavior. E.g. in MySQL using InnoDB, under `REPEATABLE READ` isolation and higher, the final insert and update _will_ block thanks to InnoDB's next-key locks (a.k.a. gap locks or predicate locks).

As mentioned [here](https://github.com/cockroachdb/cockroach/blob/91c1d5cbb5a56cd9c082d78814cd03c5471dddfa/pkg/sql/sem/tree/select.go#L1238-L1248), we're planning to add support for single-key predicate locking (i.e. on `Get`) in order to allow [uniqueness checks on regional by row tables](https://github.com/cockroachdb/cockroach/issues/110873) under read committed isolation. That won't be sufficient to change this behavior of SELECT FOR UPDATE, however. To make SELECT FOR UPDATE prevent phantoms in all cases, we would need multi-key predicate locking (i.e. predicate locking on `Scan`).

Jira issue: CRDB-36814

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.