Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
michae2 opened this issue Mar 18, 2024 · 1 comment
Open
Labels
A-read-committed Related to the introduction of Read Committed C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) docs-done docs-known-limitation T-kv KV Team
Projects

Comments

@michae2
Copy link
Collaborator

michae2 commented Mar 18, 2024

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:

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, 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 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

@michae2 michae2 added C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) docs-known-limitation T-kv KV Team A-read-committed Related to the introduction of Read Committed labels Mar 18, 2024
@blathers-crl blathers-crl bot added this to Incoming in KV Mar 18, 2024
@michae2
Copy link
Collaborator Author

michae2 commented Mar 18, 2024

(This is documented in the When to use locking reads section of our read committed docs.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-read-committed Related to the introduction of Read Committed C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) docs-done docs-known-limitation T-kv KV Team
Projects
KV
Incoming
Development

No branches or pull requests

1 participant