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/schemachanger: create partial index with inserts can fail #110216

Merged
merged 1 commit into from Sep 13, 2023

Conversation

fqazi
Copy link
Collaborator

@fqazi fqazi commented Sep 7, 2023

Previously, the temporary index created during CREATE INDEX with partial indexes did not correctly copy over the predicate. If an insert and a CREATE INDEX (for partial indexes) were run concurrently, the CREATE INDEX could fail since the temporary index would contain extra rows. Eventually, validation would fail. This patch copies the embedded expression for partial indexes to address this.

Fixes: #110198

Release note (bug fix): CREATE INDEX for partial indexes could fail with "ERROR: duplicate key value violates unique constraint" if concurrent inserts happened simultaneously.

@fqazi fqazi requested a review from a team as a code owner September 7, 2023 20:48
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@fqazi fqazi added branch-release-23.1 Used to mark GA and release blockers and technical advisories for 23.1 backport-23.1.x Flags PRs that need to be backported to 23.1 and removed branch-release-23.1 Used to mark GA and release blockers and technical advisories for 23.1 labels Sep 8, 2023
isSecondary = true
}
tempID := srcIdx.TemporaryIndexID
newTempSpec.temporary = &scpb.TemporaryIndex{
Index: srcIdx,
IsUsingSecondaryEncoding: isSecondary,
EmbeddedExpr: expr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the indexSpec be marked as temporary instead of copying parts of the top level spec into the temporary section?

Copy link
Collaborator Author

@fqazi fqazi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @ecwall)


pkg/sql/schemachanger/scbuild/internal/scbuildstmt/helpers.go line 701 at r1 (raw file):

Previously, ecwall (Evan Wall) wrote…

Can the indexSpec be marked as temporary instead of copying parts of the top level spec into the temporary section?

So, I think you are suggesting that an indexSpec for a temporary is a copy with just a flag flipped. I think that works for some things, but then there are a bunch of rewrites that happen below to assign IDs. Also, the apply I think would need to generate a TemporryIndex element from the original/primary secondary index elements.

I think in an ideal world SecondaryIndex == TemporaryIndex in terms of content minus the encoding indicator. But we also can't poke at scpb since that's written to descriptors :(

@@ -279,6 +279,7 @@ message SecondaryIndex {
message TemporaryIndex {
Index embedded_index = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
bool is_using_secondary_encoding = 2;
Expression embedded_expr = 3 [(gogoproto.nullable) = true];
Copy link
Contributor

@Xiang-Gu Xiang-Gu Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add some comments around this new field
nit: if you really intend this to be embedded (via (gogoproto.embed) = true), then consider changing the name.

Comment on lines 17 to 18
# Each insert will be injected thrice per stage, so we should always,
# see a count of 2.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add or modify the comments to help readers understand why a count of 2?

@@ -10,13 +10,14 @@ INSERT INTO t VALUES($stageKey + 1, 'b');
INSERT INTO t VALUES($stageKey + 2, 'c');
DELETE FROM t WHERE v = 'a' and k=$stageKey;
INSERT INTO t VALUES($stageKey, 'a');
UPDATE t SET v='a' WHERE k > 0;
UPDATE t SET v='a' WHERE k % 2 = 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a note as to why % 2 is being used in favor of > 0?

Previously, the temporary index created during CREATE INDEX with
partial indexes did not correctly copy over the predicate. If an
insert and a CREATE INDEX (for partial indexes) were run
concurrently, the CREATE INDEX could fail since the temporary
index would contain extra rows. Eventually, validation would fail.
This patch copies the embedded expression for partial indexes to address
this.

Fixes: cockroachdb#110198

Release note (bug fix): CREATE INDEX for partial indexes could fail with
"ERROR: duplicate key value violates unique constraint" if concurrent inserts
happened simultaneously.
Copy link
Collaborator Author

@fqazi fqazi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 5 files at r2.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @chrisseto, @ecwall, and @Xiang-Gu)


pkg/sql/schemachanger/testdata/end_to_end/create_index/create_index.definition line 13 at r1 (raw file):

Previously, chrisseto (Chris Seto) wrote…

Can you add a note as to why % 2 is being used in favor of > 0?

Done.


pkg/sql/schemachanger/testdata/end_to_end/create_index/create_index.definition line 18 at r1 (raw file):

Previously, Xiang-Gu (Xiang Gu) wrote…

can we add or modify the comments to help readers understand why a count of 2?

Done.

Copy link
Contributor

@chrisseto chrisseto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Collaborator

@rafiss rafiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice finds!

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @chrisseto, @ecwall, and @Xiang-Gu)

@fqazi
Copy link
Collaborator Author

fqazi commented Sep 13, 2023

@Xiang-Gu @chrisseto @rafiss @ecwall TFTR!

bors r+

@craig
Copy link
Contributor

craig bot commented Sep 13, 2023

Build succeeded:

@craig craig bot merged commit 8316976 into cockroachdb:master Sep 13, 2023
8 checks passed
@blathers-crl
Copy link

blathers-crl bot commented Sep 13, 2023

Encountered an error creating backports. Some common things that can go wrong:

  1. The backport branch might have already existed.
  2. There was a merge conflict.
  3. The backport branch contained merge commits.

You might need to create your backport manually using the backport tool.


error creating merge commit from 5e8569d to blathers/backport-release-23.1-110216: POST https://api.github.com/repos/cockroachdb/cockroach/merges: 409 Merge conflict []

you may need to manually resolve merge conflicts with the backport tool.

Backport to branch 23.1.x failed. See errors above.


🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

@daniel-crlabs
Copy link
Contributor

@fqazi @rafiss Any idea when this fix will be released? We have customers running into this issue duplicate key value violates unique constraint and having to disable it with what's shown below (customer is on 23.1.11)

SET use_declarative_schema_changer = off;

Once the customers do the above they are able to create the index. Are there any negative consequences to disabling the declarative schema changer in this scenario (creating indexes)? Can they safely move forward with SET use_declarative_schema_changer = off for any session where they this king of index? Example below:

CREATE INDEX index_name_here 
ON table_name_here (bucketnum, keyname) 
WHERE (validstate = 3) AND (versioned = true);

@fqazi
Copy link
Collaborator Author

fqazi commented Feb 26, 2024

@daniel-crlabs The fix is already merged into 23.1.12 they just need to move up: #110584. Ideally they should only disable the declarative schema changer for CREATE INDEX (especially if they have larger data sets).

@daniel-crlabs
Copy link
Contributor

Thank you, I'll let them know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-23.1.x Flags PRs that need to be backported to 23.1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sql/schemachanger: CREATE INDEX with partial indexes with concurrent inserts can fail
7 participants