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: alter primary key is not idempotent #61345

Merged
merged 1 commit into from
Mar 3, 2021

Conversation

fqazi
Copy link
Collaborator

@fqazi fqazi commented Mar 2, 2021

Fixes: #59307

Previously, issuing an alter primary key with the exact same
definition as the current primary key would cause expensive
indexes to be recreated even when there was no logical change.
There was overhead involved in creating these indexes and as
a side effect existing indexes for the primary key would also
get needlessly renamed. To address this, this patch uses the
AST node for alter primary key to determine if the requested
change is logically the same before any operation is executed.
If its logically the same then it becomes a no-op.

Release justification: This is a low risk change with good benefit
to the user base by reducing extra indexes getting made and rename
operations.

Release note (bug fix): Alter primary key was not idempotent, so
logical equivalent changes to primary keys would unnecessarily
create new indexes.

@fqazi fqazi requested a review from a team March 2, 2021 17:00
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@fqazi fqazi force-pushed the alterIdempotent branch 3 times, most recently from 633fb6c to d8704f5 Compare March 2, 2021 18:31
@fqazi fqazi requested review from a team and pbardea and removed request for a team March 2, 2021 18:31
@fqazi fqazi force-pushed the alterIdempotent branch from 43cb337 to d8704f5 Compare March 2, 2021 19:03
Copy link
Contributor

@pbardea pbardea 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 @fqazi)


pkg/ccl/backupccl/backup_test.go, line 832 at r1 (raw file):

	sqlDB.Exec(t, `CREATE UNIQUE INDEX id2 ON data.bank (id)`)
	// This statement will be a no-op since the primary key is already ID
	sqlDB.Exec(t, `ALTER TABLE data.bank ALTER PRIMARY KEY USING COLUMNS(id)`)

I think this test has actually rotted a bit and the way that we create data.bank has changed under it. Let's remove this ALTER TABLE ... PK entirely.


pkg/ccl/backupccl/backup_test.go, line 842 at r1 (raw file):

		t.Fatalf("expected %d rows, got %d", numAccounts, exportedRows)
	}
	expectedIndexEntries := numAccounts * 2 // PK and old secondary idx

This comment has also rotted, PK actually isn't included in this count. I think the 2 indexes are the old secondary idx (balance_idx) and the new index id2. Can we update this comment to: // Indexes id2 and balance_idx? Thanks!

@fqazi fqazi force-pushed the alterIdempotent branch from d8704f5 to 205ae0c Compare March 2, 2021 19:13
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 @pbardea)


pkg/ccl/backupccl/backup_test.go, line 832 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

I think this test has actually rotted a bit and the way that we create data.bank has changed under it. Let's remove this ALTER TABLE ... PK entirely.

Done.


pkg/ccl/backupccl/backup_test.go, line 842 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

This comment has also rotted, PK actually isn't included in this count. I think the 2 indexes are the old secondary idx (balance_idx) and the new index id2. Can we update this comment to: // Indexes id2 and balance_idx? Thanks!

Done.

Copy link
Contributor

@pbardea pbardea left a comment

Choose a reason for hiding this comment

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

Backup test changes LGTM!

Copy link
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

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

Something seems off with something related to the multi-region code. I have a feeling it relates to

if err := params.p.AlterPrimaryKey(
but I haven't given it more than a cursory pass. I think that the locality config can imply an implicit partitioning column which we need to watch out for.

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

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.

Yes, that case is broken, need additional logic to handle it.

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

@fqazi fqazi force-pushed the alterIdempotent branch from 205ae0c to 0488e50 Compare March 3, 2021 18:07
@fqazi fqazi requested a review from ajwerner March 3, 2021 19:16
Copy link
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

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

:lgtm: mod nits

Reviewed 1 of 3 files at r1, 1 of 2 files at r2.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @fqazi and @pbardea)


pkg/sql/alter_primary_key.go, line 534 at r2 (raw file):

	alterPKNode *tree.AlterTableAlterPrimaryKey,
	alterPrimaryKeyLocalitySwap *alterPrimaryKeyLocalitySwap,
) (bool, error) {

nit: name returned booleans, I find it aids readability. You can use _ for the error.


pkg/sql/alter_primary_key.go, line 566 at r2 (raw file):

		}

		if len(oldPK.IndexDesc().Interleave.Ancestors) == 0 {

nit: things wouldn't be so long if you just assigned oldPK.IndexDesc().Interleave.Ancestors to a variable.


pkg/sql/alter_primary_key.go, line 607 at r2 (raw file):

	// then recreate indexes.
	if alterPrimaryKeyLocalitySwap != nil {
		if !alterPrimaryKeyLocalitySwap.localityConfigSwap.NewLocalityConfig.Equal(alterPrimaryKeyLocalitySwap.localityConfigSwap.OldLocalityConfig) {

nit: how about some line wrapping or perhaps some variables to make this more readable.

@fqazi
Copy link
Collaborator Author

fqazi commented Mar 3, 2021

Thanks for the review!

@fqazi fqazi force-pushed the alterIdempotent branch from 0488e50 to bb99570 Compare March 3, 2021 21:28
@fqazi
Copy link
Collaborator Author

fqazi commented Mar 3, 2021

bors r+

Fixes: cockroachdb#59307

Previously, issuing an alter primary key with the exact same
definition as the current primary key would cause expensive
indexes to be recreated even when there was no logical change.
There was overhead involved in creating these indexes and as
a side effect existing indexes for the primary key would also
get needlessly renamed. To address this, this patch uses the
AST node for alter primary key to determine if the requested
change is logically the same before any operation is executed.
If its logically the same then it becomes a no-op.

Release justification: This is a low risk change with good benefit
to the user base by reducing extra indexes getting made and rename
operations.

Release note (bug fix): Alter primary key was not idempotent, so
logical equivalent changes to primary keys would unnecessarily
create new indexes.
@fqazi fqazi force-pushed the alterIdempotent branch from bb99570 to 03319af Compare March 3, 2021 21:33
@craig
Copy link
Contributor

craig bot commented Mar 3, 2021

Canceled.

@fqazi
Copy link
Collaborator Author

fqazi commented Mar 3, 2021

bors r+

@craig
Copy link
Contributor

craig bot commented Mar 3, 2021

Build succeeded:

@craig craig bot merged commit 44ea98b into cockroachdb:master Mar 3, 2021
ajwerner added a commit to ajwerner/cockroach that referenced this pull request Mar 10, 2021
The code in cockroachdb#61345 added a test that, under stress, nicely revealed a bug.
The bug is that we're mutating the AST in place and then, on retries, we hit
an error. The fix is to not mutate the AST.

I wish I had a more comprehensive testing strategy to ensure this didn't
happen. On some level, we could clone the AST when passing it to various DDL
plan node constructors. That's very defensive but also probably fine. Another
thing that would be cool would be to just assert that after planning the AST
did not change.

Touches cockroachdb#60824.

Release note: None
ajwerner added a commit to ajwerner/cockroach that referenced this pull request Mar 10, 2021
The code in cockroachdb#61345 added a test that, under stress, nicely revealed a bug.
The bug is that we're mutating the AST in place and then, on retries, we hit
an error. The fix is to not mutate the AST.

I wish I had a more comprehensive testing strategy to ensure this didn't
happen. On some level, we could clone the AST when passing it to various DDL
plan node constructors. That's very defensive but also probably fine. Another
thing that would be cool would be to just assert that after planning the AST
did not change.

Touches cockroachdb#60824.

Release note: None
ajwerner added a commit to ajwerner/cockroach that referenced this pull request Mar 10, 2021
The code in cockroachdb#61345 added a test that, under stress, nicely revealed a bug.
The bug is that we're mutating the AST in place and then, on retries, we hit
an error. The fix is to not mutate the AST.

I wish I had a more comprehensive testing strategy to ensure this didn't
happen. On some level, we could clone the AST when passing it to various DDL
plan node constructors. That's very defensive but also probably fine. Another
thing that would be cool would be to just assert that after planning the AST
did not change.

Touches cockroachdb#60824.

Release note: None
craig bot pushed a commit that referenced this pull request Mar 10, 2021
61784: sql: stop mutating AST in AlterPrimaryKey r=fqazi a=ajwerner

The code in #61345 added a test that, under stress, nicely revealed a bug.
The bug is that we're mutating the AST in place and then, on retries, we hit
an error. The fix is to not mutate the AST.

I wish I had a more comprehensive testing strategy to ensure this didn't
happen. On some level, we could clone the AST when passing it to various DDL
plan node constructors. That's very defensive but also probably fine. Another
thing that would be cool would be to just assert that after planning the AST
did not change.

Touches #60824.

Release note: None

61791: kv/kvserver: skip TestEagerReplication r=RaduBerinde a=adityamaru

Refs: #54646

Reason: flaky test

Generated by bin/skip-test.

Release justification: non-production code changes

Release note: None

61796: bazel: make `pkg/internal/rsg/yacc` test runnable in Bazel r=rickystewart a=rickystewart

This test was missing a dependency on `sql.y`.

Release note: None

61797: bazel: make `pkg/sql/parser` test runnable in Bazel r=rickystewart a=rickystewart

There was a typo in the `genrule` definition here.

Release note: None

Co-authored-by: Andrew Werner <[email protected]>
Co-authored-by: Aditya Maru <[email protected]>
Co-authored-by: Ricky Stewart <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sql: ALTER PRIMARY KEY is not idempotent
4 participants