Skip to content

sql: SELECT FOR UPDATE on multi-column-family tables under read committed does not lock completely-NULL column families #116836

@michae2

Description

@michae2

In 23.2 we added a new implementation of SELECT FOR UPDATE, which is initially used only for Read Committed isolation (and Serializable isolation when optimizer_use_lock_op_for_serializable is true). As of #116170 this implementation of SELECT FOR UPDATE locks all column families of selected rows, with one exception: it does not lock column families of rows for which the value of every column is NULL.

This means, for tables with multiple column families, SELECT FOR UPDATE might not block an UPDATE that changes a NULL value to a non-NULL value.

Here's a demonstration:

SET CLUSTER SETTING sql.txn.read_committed_isolation.enabled = true;

-- A multi-column-family table with a family which can be entirely NULL (f2).
CREATE TABLE abcd (
  a INT NOT NULL,
  b INT NOT NULL,
  c INT NOT NULL,
  d INT NULL,
  PRIMARY KEY (a),
  FAMILY f0 (a, b),
  FAMILY f1 (c),
  FAMILY f2 (d)
);
INSERT INTO abcd VALUES (4, 5, 6, 7), (8, 9, 10, NULL);

-- Under read committed isolation we lock the first row. This locks all column families.
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * FROM abcd WHERE a = 4 FOR UPDATE;

-- Mutations performed by other sessions block.
UPDATE abcd SET d = 17 WHERE a = 4 AND b = 5;

-- The first transaction will not see the update.
-- After the first transaction finishes, the update can proceed.
SELECT * FROM abcd WHERE a = 4;
COMMIT;

-- But if we lock the second row, this locks all column families *except* f2, because d is NULL.
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * FROM abcd WHERE a = 8 FOR UPDATE;

-- Mutations performed by other sessions that only modify the unlocked column family will not block.
UPDATE abcd SET d = 11 WHERE a = 8 AND b = 9;

-- The first transaction will see the update.
SELECT * FROM abcd WHERE a = 8;
COMMIT;

Jira issue: CRDB-34802
Epic CRDB-38938

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-read-committedRelated to the introduction of Read CommittedC-bugCode not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior.T-sql-queriesSQL Queries Teamdocs-donedocs-known-limitation

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions