-
Notifications
You must be signed in to change notification settings - Fork 4.1k
sql, kv: support explicit unique checks under non-serializable isolations for INSERT & UPDATE #110873
Description
In CockroachDB, most unique constraints are enforced by an accompanying unique index. The uniqueness check which maintains the constraint is simply the use of ConditionalPut instead of Put when writing a row to that index.
However, for unique constraints without an accompanying unique index, the uniqueness check is an explicit search in the target table for any potential conflicting rows. Under read committed isolation this search must use predicate locking, which is not yet implemented.
Consequently, any INSERT, UPDATE, or UPSERT that needs to perform an explicit unique check is not yet support under read committed isolation.
This affects inserts, updates, or upserts into:
UNIQUE WITHOUT INDEXconstraints (an experimental feature).UNIQUEandPRIMARY KEYconstraints on tables usingPARTITION ALL BY(an experimental feature).UNIQUEandPRIMARY KEYconstraints on tables usingLOCALITY REGIONAL BY ROW, when (a) the region is not included in the constraint and (b) cannot be computed from the constraint columns.
The last case is the most common and the most complex, so here are some examples with and without explicit unique checks:
-- This table requires explicit unique checks during inserts and updates
-- because neither the primary key nor the unique constraint include region.
CREATE TABLE ab (
a INT NOT NULL,
b INT,
PRIMARY KEY (a),
UNIQUE (b)
) LOCALITY REGIONAL BY ROW;
-- Hence this insert is not yet supported under read committed isolation.
INSERT INTO ab VALUES (1, 2);
-- This table does not require an explicit unique check because both the
-- primary key and the unique constraint start with the region.
CREATE TABLE cd (
c INT NOT NULL,
d INT,
region crdb_internal_region NOT NULL,
PRIMARY KEY (region, c),
UNIQUE (region, d)
) LOCALITY REGIONAL BY ROW AS region;
-- Hence this insert is supported under read committed isolation.
INSERT INTO cd VALUES (3, 4, 'us-east1');
-- This table does not require an explicit unique check because the region can
-- be computed from the columns in both the primary key and the unique
-- constraint.
CREATE TABLE ef (
e INT NOT NULL,
f INT,
region crdb_internal_region NOT NULL AS (
CASE WHEN e % 2 = 0 THEN 'us-east1' ELSE 'us-west1' END
) STORED,
PRIMARY KEY (e),
UNIQUE (f, e)
) LOCALITY REGIONAL BY ROW AS region;
-- Hence this insert is supported under read committed isolation.
INSERT INTO ef VALUES (5, 6);
-- This table requires an explicit unique check because though the region can
-- be computed from the primary key, it cannot be computed from the column in
-- the unique constraint, and the unique constraint does not start with the
-- region.
CREATE TABLE gh (
g INT NOT NULL,
h INT,
region crdb_internal_region NOT NULL AS (
CASE WHEN g % 2 = 0 THEN 'us-east1' ELSE 'us-west1' END
) STORED,
PRIMARY KEY (g),
UNIQUE (h)
) LOCALITY REGIONAL BY ROW AS region;
-- Hence this insert is not yet supported under read committed isolation.
INSERT INTO gh VALUES (7, 8);
-- This table does not require an explicit unique check because even though
-- the primary key does not include region, we have special behavior to elide the
-- unique check when using gen_random_uuid().
CREATE TABLE ij (
i UUID NOT NULL DEFAULT gen_random_uuid(),
j INT,
PRIMARY KEY (i)
) LOCALITY REGIONAL BY ROW;
-- Hence these inserts are supported under read committed isolation.
INSERT INTO ij (j) VALUES (9);
INSERT INTO ij VALUES (gen_random_uuid(), 10);
-- But these inserts are not yet supported under read committed isolation.
INSERT INTO ij VALUES ('1a29408d-7530-44ad-aa12-917a2ae1c96d', 11);
SET CLUSTER SETTING sql.optimizer.uniqueness_checks_for_gen_random_uuid.enabled = true;
INSERT INTO ij (j) VALUES (12);Jira issue: CRDB-31651
Epic CRDB-38938
Metadata
Metadata
Assignees
Labels
Type
Projects
Status