-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Experimental: Multi-tenant import support in Vitess #15128
Experimental: Multi-tenant import support in Vitess #15128
Conversation
Review ChecklistHello reviewers! 👋 Please follow this checklist when reviewing this Pull Request. General
Tests
Documentation
New flags
If a workflow is added or modified:
Backward compatibility
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #15128 +/- ##
==========================================
+ Coverage 65.44% 65.61% +0.17%
==========================================
Files 1562 1563 +1
Lines 193922 194239 +317
==========================================
+ Hits 126905 127448 +543
+ Misses 67017 66791 -226 ☔ View full report in Codecov by Sentry. |
77ed0f0
to
623fc77
Compare
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
…action for them. Add vtctldclient cli commands for Apply/Get KeyspaceRoutingRules Signed-off-by: Rohit Nayak <[email protected]>
…eating the workflow and switching traffic. Signed-off-by: Rohit Nayak <[email protected]>
…les. Signed-off-by: Rohit Nayak <[email protected]>
…ate to tests. Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
…steps Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
df91cc1
to
c34783f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The basic functionality looks solid. My comments are mostly around CLI, testing and documentation. The test also looks solid, but we probably need to run it with a slightly larger dataset.
|
||
var ( | ||
// ApplyKeyspaceRoutingRules makes an ApplyKeyspaceRoutingRules gRPC call to a vtctld. | ||
ApplyKeyspaceRoutingRules = &cobra.Command{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about extending ApplyRoutingRules
and GetRoutingRules
to take optional keyspace and shard arguments? Then we won't have so many separate commands. We can then also deprecate and delete ApplyShardRoutingRules
and GetShardRoutingRules
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Keyspace, Routing and Shard rules are quite different in terms of functionality. It might be better to have them separate because of that.
We can't have a table routing rule just for a shard for example. Also each of these takes a rules file and those files cannot contain a combination of table and keyspace for example.
Maybe we can have think of a RoutingRule umbrella command: table
, keyspace
and shard
subcommands and apply
andget
actions. But it will be a non-trivial refactor.
@@ -47,6 +47,10 @@ func registerCommands(root *cobra.Command) { | |||
create.Flags().StringSliceVar(&createOptions.ExcludeTables, "exclude-tables", nil, "Source tables to exclude from copying.") | |||
create.Flags().BoolVar(&createOptions.NoRoutingRules, "no-routing-rules", false, "(Advanced) Do not create routing rules while creating the workflow. See the reference documentation for limitations if you use this flag.") | |||
create.Flags().BoolVar(&createOptions.AtomicCopy, "atomic-copy", false, "(EXPERIMENTAL) A single copy phase is run for all tables from the source. Use this, for example, if your source keyspace has tables which use foreign key constraints.") | |||
create.Flags().StringVar(&createOptions.VReplicationWorkflowOptions.AdditionalFilter, "additional-filter", "", "Additional filter to apply to the tables being copied in addition to the default filter.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to call this additional-filter
? Why can't it just be filter
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started with -filter
and then realized that we also use filter
in the _vt.vreplication
row and we will not be using the value provided for this option as the filter
but as an additional clause.
But I am fine if we want to just use -filter
.
@@ -47,6 +47,10 @@ func registerCommands(root *cobra.Command) { | |||
create.Flags().StringSliceVar(&createOptions.ExcludeTables, "exclude-tables", nil, "Source tables to exclude from copying.") | |||
create.Flags().BoolVar(&createOptions.NoRoutingRules, "no-routing-rules", false, "(Advanced) Do not create routing rules while creating the workflow. See the reference documentation for limitations if you use this flag.") | |||
create.Flags().BoolVar(&createOptions.AtomicCopy, "atomic-copy", false, "(EXPERIMENTAL) A single copy phase is run for all tables from the source. Use this, for example, if your source keyspace has tables which use foreign key constraints.") | |||
create.Flags().StringVar(&createOptions.VReplicationWorkflowOptions.AdditionalFilter, "additional-filter", "", "Additional filter to apply to the tables being copied in addition to the default filter.") | |||
create.Flags().BoolVar(&createOptions.VReplicationWorkflowOptions.UseKeyspaceRoutingRules, "use-keyspace-routing-rules", false, "Use keyspaces routing rules to route traffic to the target keyspace. This is not compatible with the --no-routing-rules flag and will override the default table routing rules mechanism.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create.Flags().BoolVar(&createOptions.VReplicationWorkflowOptions.UseKeyspaceRoutingRules, "use-keyspace-routing-rules", false, "Use keyspaces routing rules to route traffic to the target keyspace. This is not compatible with the --no-routing-rules flag and will override the default table routing rules mechanism.") | |
create.Flags().BoolVar(&createOptions.VReplicationWorkflowOptions.UseKeyspaceRoutingRules, "use-keyspace-routing-rules", false, "Use keyspace routing rules to route traffic to the target keyspace. This is not compatible with the --no-routing-rules flag and will override the default table routing rules mechanism.") |
go/cmd/vtctldclient/command/vreplication/movetables/movetables.go
Outdated
Show resolved
Hide resolved
@@ -168,6 +168,7 @@ func waitForQueryResult(t *testing.T, conn *mysql.Conn, database string, query s | |||
for { | |||
qr := execVtgateQuery(t, conn, database, query) | |||
require.NotNil(t, qr) | |||
log.Infof("query %q returned %v", query, qr.Rows) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to keep this log line for merge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
const waitTimeout = 10 * time.Minute | ||
|
||
func TestMultiTenant(t *testing.T) { | ||
setSidecarDBName("_vt") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really required? or just making it explicit that we are using the default sidecar DB?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default is currently __vt_e2e-test
which is very painful to type in the mysql cli, so I have been using _vt
for new tests. I guess we should just use the complex value for some tests and _vt
for the rest. Will do it in my next e2e refactor.
defer func() { | ||
defaultRdonly = origDefaultRdonly | ||
}() | ||
defaultRdonly = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment here will be useful. I found the package level var definition and understood that it means we don't run any RDONLY tablets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
} | ||
|
||
func (mtm *multiTenantMigration) initTenantData(t *testing.T, tenantId int64, userKeyspace string) { | ||
mtm.insertSomeData(t, tenantId, userKeyspace, 10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have 30 tenants, and table has 10 rows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently 30 tenants. Test nitially inserts 10 rows and then a few more additionally. Changed all literals to use constants.
@@ -38,6 +38,7 @@ CREATE TABLE IF NOT EXISTS vreplication | |||
`component_throttled` varchar(255) NOT NULL DEFAULT '', | |||
`workflow_sub_type` int NOT NULL DEFAULT '0', | |||
`defer_secondary_keys` tinyint(1) NOT NULL DEFAULT '0', | |||
`options` json NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably start adding sql comments when we add new columns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. Added. I plan to create a documentation PR soon which adds comments on all tables for existing columns as well in the sidecar schema.
go/vt/vtctl/workflow/utils.go
Outdated
@@ -112,11 +113,11 @@ func validateNewWorkflow(ctx context.Context, ts *topo.Server, tmc tmclient.Tabl | |||
}{{ | |||
fmt.Sprintf("select 1 from _vt.vreplication where db_name=%s and workflow=%s", encodeString(primary.DbName()), encodeString(workflow)), | |||
fmt.Sprintf("workflow %s already exists in keyspace %s on tablet %v", workflow, keyspace, primary.Alias), | |||
}, { | |||
}, /* { // temporarily comenting this, since it doesn't allow to create a new workflow if there is a frozen workflow. Need to check if we really need this validation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be reverted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this check. Added details in Description.
…ing rules will not be large Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
…uncExpr required a change in a unit test helper. Uncomment frozen workflow code for now so that unit tests run. Signed-off-by: Rohit Nayak <[email protected]>
…n workflows Signed-off-by: Rohit Nayak <[email protected]>
Signed-off-by: Rohit Nayak <[email protected]>
…ime in CI. Let it run in its own workflow for now to isolate any issues and allow running it several times Signed-off-by: Rohit Nayak <[email protected]>
55e31be
to
3343c15
Compare
…dd ReverseTraffic to e2e tests. Some refactor of e2e test. Signed-off-by: Rohit Nayak <[email protected]>
Replaced with #15503 |
Description
While importing from a multi-tenant database, using MoveTables, it is possible one wants to only import some of the tenants. This PR allows the user to specify an additional filter like
tenant_id=1
. This filter is applied to both the forward and reverse workflows.It also adds keyspace routing rules, which allow entire keyspaces to be routed to the source or target keyspace for MoveTables workflows, depending on whether are in progress or switched, respectively.
For applications that use a database qualifier for their per-tenant queries and the qualifiers do not match the source keyspace defined in Vitess, an option is added to also route this database to the same route pointed to by the source keyspace.
MoveTables changes
There are three new options to MoveTables
--use-keyspace-routing-rules
: uses keyspace routing rules instead of table routing rules--source-keyspace-elias
: also add provided name as alias while mapping the source keyspace to the source or target keyspace, depending on whether traffic has been switched or not--additional-filter
: adds the provided sqlwhere
clause predicate to the forward and reverse workflowbinlogsource
filters.Related changes
Frozen workflows
We now allow creating new workflows even if there is a
frozen
workflow on the target.Frozen workflows are those which have switched writes. They have the
message
column of the_vt.vreplication
row set tofrozen
. This is used for various validations at the present like not startingvdiff
s for it or creating a new movetables/reshard workflow if there are such workflows.This validation and mechanism is a legacy hack to prevent workflows which should not restart, to be restarted by mistake by vdiffs and reshards. The issue discusses this and suggests improvements for improving this.
The frozen workflows will be deleted on a
Complete
. But in our case we may have workflows with switched traffic in play because, for large number of tenants, we will expect there to be several concurrent workflows running in different stages. Hence the need to remove this validation.This relaxation doesn't affect the current validation that ensures vdiffs will not start for frozen workflows. The above issue will review and fix any gaps that arise from the removal of this validation in the current Vitess version.
TBD:
Related Issue(s)
#15403
Checklist