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: allow atomic name swaps #70334

Merged
merged 3 commits into from
Nov 4, 2021
Merged

Conversation

postamar
Copy link
Contributor

@postamar postamar commented Sep 16, 2021

This PR deprecates and disables usage of the draining names mechanism on catalog descriptors. When renaming or dropping a table/database/schema/type, the namespace entry is now modified in-transaction. This makes it possible to swap names in-transaction. On the other hand, names may be inconsistently resolved to either the old or the new target in specific circumstances.

Fixes #54562.

@cockroach-teamcity
Copy link
Member

This change is Reviewable

@postamar postamar force-pushed the disable-draining-names branch from 6f0a649 to 4f9c1a7 Compare September 17, 2021 15:34
@postamar postamar changed the title [WIP] sql: allow atomic name swaps sql: allow atomic name swaps Sep 17, 2021
@postamar postamar force-pushed the disable-draining-names branch from 4f9c1a7 to 622a06d Compare September 17, 2021 16:59
@postamar
Copy link
Contributor Author

This PR is best reviewed commit-by-commit. We might want more tests but I'm not quite sure what to add. I'm all ears.

@postamar postamar marked this pull request as ready for review September 17, 2021 17:01
@postamar postamar requested a review from a team September 17, 2021 17:01
@postamar postamar requested a review from a team as a code owner September 17, 2021 17:01
@postamar postamar requested review from a team September 17, 2021 17:01
@postamar postamar requested a review from a team as a code owner September 17, 2021 17:01
@postamar postamar requested review from dt and removed request for a team and dt September 17, 2021 17:01
@postamar postamar force-pushed the disable-draining-names branch from 622a06d to 961e6a2 Compare September 17, 2021 18:44
@postamar postamar force-pushed the disable-draining-names branch 5 times, most recently from 6e0bb47 to 762e24d Compare October 15, 2021 18:08
@postamar postamar requested a review from ajwerner October 26, 2021 17:33
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.

I'd very much like to see logic tests that exercise these atomic name changes in various ways. I don't see any new logic tests.


Some more snippets that I think should get some updated commentary or, at least, consideration:

if desc.GetName() != name {
// Immediately after a RENAME an old name still points to the descriptor
// during the drain phase for the name. Do not return a descriptor during
// draining.
return nil, nil
}

// descNames is the set of names which a read or written
// descriptor took on at some point in its lifetime. Everything added to
// uncommittedDescriptors is added to descNames as well
// as all of the known draining names. The idea is that if we find that
// a name is not in the above map but is in the set, then we can avoid
// doing a lookup.
descNames nstree.Set

After very brief reflection, I think the second piece could still be relevant.

Reviewed 6 of 25 files at r1, 11 of 15 files at r2, 33 of 37 files at r3, 12 of 12 files at r4, all commit messages.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)

@postamar postamar force-pushed the disable-draining-names branch 2 times, most recently from 8003d30 to 91f0cc6 Compare November 3, 2021 00:34
Copy link
Contributor Author

@postamar postamar left a comment

Choose a reason for hiding this comment

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

Thanks for taking a look!

I've added a new logic test suite to exercise these changes. Did I cover enough cases? I'm honestly bad at coming up with these.

I've added TODOs for each of these snippets. Mixed-version clusters mean that we can't do what we really want to do in the descs collection until 22.1 comes out anyway.

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

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.

I've added TODOs for each of these snippets. Mixed-version clusters mean that we can't do what we really want to do in the descs collection until 22.1 comes out anyway.

Ah yeah, makes sense. I'm a bit sad I wasn't in the mixed-version mindset in the first read through.


abstract thought: are there any hazards with drop cascades and then failures to resolve fully qualified names?


On the whole, :lgtm:. Let me stew on some concerning thoughts until tomorrow but I'm pretty pleased with this.

Reviewed 1 of 52 files at r5, 4 of 37 files at r6, 9 of 15 files at r7, all commit messages.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @ajwerner and @postamar)


pkg/migration/migrations/ensure_no_draining_names.go, line 44 at r7 (raw file):

	cte2
WHERE
	COALESCE(json_array_length(d->'drainingNames'), 0) > 0;

add a LIMIT 1 then consider just using the Buffered version of the internal executor for some simpler processing?


pkg/sql/logictest/testdata/logic_test/rename_atomic, line 4 at r7 (raw file):

CREATE DATABASE db;
CREATE DATABASE db_new;

what I'd like to see added here is the usage of the renamed objects in the transaction after the renaming statements to demonstrate that they are indeed usable.


pkg/sql/logictest/testdata/logic_test/table, line 859 at r7 (raw file):


user root

it feels like you could preserve a version of this test without the errors


pkg/sql/logictest/testdata/logic_test/views, line 848 at r7 (raw file):

CREATE VIEW db2.v2 AS SELECT a+b+c+d FROM cd, db1.public.ab

# Unit test for #60737

it feels like you can rework this test to be a working test if you remove the errors and the rollbacks.

Copy link
Contributor Author

@postamar postamar left a comment

Choose a reason for hiding this comment

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

abstract thought: are there any hazards with drop cascades and then failures to resolve fully qualified names?

I honestly couldn't tell you at this point, could you elaborate please? It's been a while. Do you have in mind the following: adding a unit test which drop-cascades a bunch of stuff, blocks the schema change job via a testing knob, and concurrently tries to resolve fully-qualified names? Basically testing that the job does the "right thing" with names now that it no longer drains the names at the very end of its execution?

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


pkg/migration/migrations/ensure_no_draining_names.go, line 44 at r7 (raw file):

Previously, ajwerner wrote…

add a LIMIT 1 then consider just using the Buffered version of the internal executor for some simpler processing?

Done.


pkg/sql/logictest/testdata/logic_test/rename_atomic, line 4 at r7 (raw file):

Previously, ajwerner wrote…

what I'd like to see added here is the usage of the renamed objects in the transaction after the renaming statements to demonstrate that they are indeed usable.

Done, I think.


pkg/sql/logictest/testdata/logic_test/table, line 859 at r7 (raw file):

Previously, ajwerner wrote…

it feels like you could preserve a version of this test without the errors

That's true, but what are we testing in that case? It feels like the purpose of this deleted test is to exercise the error messages. Would you like me to extend the rename_atomic suite with cases involving different object types: tables, types, views etc?


pkg/sql/logictest/testdata/logic_test/views, line 848 at r7 (raw file):

Previously, ajwerner wrote…

it feels like you can rework this test to be a working test if you remove the errors and the rollbacks.

Same comment as above regarding what this test exercises.

@postamar postamar force-pushed the disable-draining-names branch from 91f0cc6 to bffd364 Compare November 3, 2021 20:39
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

Marius Posta added 2 commits November 4, 2021 11:26
This refactoring commit is the first step to removing these fields and
their associated methods.

See issue cockroachdb#54562.

Release note: None
This commit introduces a new cluster version, keyed as
AvoidDrainingNames, which allows atomic name swaps between two
tables/databases/schemas/types. This means we're no longer populating
the draining names of a descriptor, instead we're updating the namespace
table in the same transaction.

The price to pay for all of this is that there is a period of time
following a name swap in which the name may refer to either of the two
descriptors.

Fixes cockroachdb#54562.

Release note (sql change): It's now possible to swap names (for tables,
etc.) in the same transaction. For example:

  CREATE TABLE foo();
  BEGIN;
  ALTER TABLE foo RENAME TO bar;
  CREATE TABLE foo();
  COMMIT;

Previously, we'd be getting a "relation ... already exists" error.
@postamar postamar force-pushed the disable-draining-names branch from bffd364 to 3daa0db Compare November 4, 2021 15:28
@postamar
Copy link
Contributor Author

postamar commented Nov 4, 2021

Thanks for the review!

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 the one comment

Reviewed 2 of 53 files at r9, 6 of 37 files at r10, 9 of 15 files at r11, all commit messages.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @ajwerner and @postamar)


pkg/migration/migrations/ensure_no_draining_names.go, line 75 at r11 (raw file):

		log.Infof(ctx, "descriptor with ID %d and name %q still has draining names", id, name)
	}
	panic("unreachable")

how is this unreachable? If the context gets canceled, won't you be here?


pkg/sql/logictest/testdata/logic_test/table, line 859 at r7 (raw file):

Previously, postamar (Marius Posta) wrote…

That's true, but what are we testing in that case? It feels like the purpose of this deleted test is to exercise the error messages. Would you like me to extend the rename_atomic suite with cases involving different object types: tables, types, views etc?

It's okay, I think it's fine.

This commit complements the preceding commit by adding a migration which
waits for all descriptors to no longer have any draining names. Since
the previous cluster version prevents the addition of new draining
names, this new cluster version guarantees that the draining names
mechanism is no longer in use. All code pertaining to draining names
can therefore be deleted after the upcoming release, which is 22.1.

Release note: None
@postamar postamar force-pushed the disable-draining-names branch from 3daa0db to d7425cd Compare November 4, 2021 16:36
@postamar
Copy link
Contributor Author

postamar commented Nov 4, 2021

how is this unreachable? If the context gets canceled, won't you be here?

Gaah I keep forgetting about that. Thanks, good catch! Returning ctx.Err() instead, on your advice (thank you for that too).

@postamar
Copy link
Contributor Author

postamar commented Nov 4, 2021

bors r+

@craig
Copy link
Contributor

craig bot commented Nov 4, 2021

Build succeeded:

@craig craig bot merged commit 5e87a89 into cockroachdb:master Nov 4, 2021
@postamar postamar deleted the disable-draining-names branch November 4, 2021 18:51
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: can't atomically swap names for catalog entries
3 participants