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

MoveTables: remove option to specify source keyspace alias for multi-tenant migrations #15712

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ func registerCommands(root *cobra.Command) {
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.WorkflowOptions.TenantId, "tenant-id", "", "(EXPERIMENTAL) The tenant ID to use for the MoveTables workflow into a multi-tenant keyspace.")
create.Flags().StringVar(&createOptions.WorkflowOptions.SourceKeyspaceAlias, "source-keyspace-alias", "", "(EXPERIMENTAL) Used currently only for multi-tenant migrations. This value will be used instead of the source keyspace name in the keyspace routing rules.")
create.Flags().BoolVar(&createOptions.WorkflowOptions.StripShardedAutoIncrement, "remove-sharded-auto-increment", true, "If moving the table(s) to a sharded keyspace, remove any auto_increment clauses when copying the schema to the target as sharded keyspaces should rely on either user/application generated values or Vitess sequences to ensure uniqueness.")
base.AddCommand(create)

Expand Down
40 changes: 10 additions & 30 deletions go/test/endtoend/vreplication/multi_tenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ const (
tenantMigrationStatusMigrating
tenantMigrationStatusMigrated

sourceKeyspaceTemplate = "s%d"
sourceAliasKeyspaceTemplate = "a%d"
targetKeyspaceName = "mt"
sourceKeyspaceTemplate = "s%d"
targetKeyspaceName = "mt"

numTenants = 10
numInitialRowsPerTenant = 10
Expand Down Expand Up @@ -130,7 +129,6 @@ func TestMultiTenantSimple(t *testing.T) {

tenantId := int64(1)
sourceKeyspace := getSourceKeyspace(tenantId)
sourceAliasKeyspace := getSourceAliasKeyspace(tenantId)
_, err = vc.AddKeyspace(t, []*Cell{vc.Cells["zone1"]}, sourceKeyspace, "0", stVSchema, stSchema, 1, 0, getInitialTabletIdForTenant(tenantId), nil)
require.NoError(t, err)

Expand Down Expand Up @@ -163,19 +161,16 @@ func TestMultiTenantSimple(t *testing.T) {
sourceKeyspace: sourceKeyspace,
createFlags: []string{
"--tenant-id", strconv.FormatInt(tenantId, 10),
"--source-keyspace-alias", sourceAliasKeyspace,
},
})

preSwitchRules := &vschemapb.KeyspaceRoutingRules{
Rules: []*vschemapb.KeyspaceRoutingRule{
{FromKeyspace: "a1", ToKeyspace: "s1"},
{FromKeyspace: "s1", ToKeyspace: "s1"},
},
}
postSwitchRules := &vschemapb.KeyspaceRoutingRules{
Rules: []*vschemapb.KeyspaceRoutingRule{
{FromKeyspace: "a1", ToKeyspace: "mt"},
{FromKeyspace: "s1", ToKeyspace: "mt"},
},
}
Expand All @@ -187,25 +182,21 @@ func TestMultiTenantSimple(t *testing.T) {
mt.Create()
validateKeyspaceRoutingRules(t, vc, primaries, rulesMap, false)
// Note: we cannot insert into the target keyspace since that is never routed to the source keyspace.
for _, ks := range []string{sourceKeyspace, sourceAliasKeyspace} {
lastIndex = insertRows(lastIndex, ks)
}
lastIndex = insertRows(lastIndex, sourceKeyspace)
waitForWorkflowState(t, vc, fmt.Sprintf("%s.%s", targetKeyspace, mt.workflowName), binlogdatapb.VReplicationWorkflowState_Running.String())
mt.SwitchReadsAndWrites()
validateKeyspaceRoutingRules(t, vc, primaries, rulesMap, true)
// Note: here we have already switched and we can insert into the target keyspace and it should get reverse
// replicated to the source keyspace. The source and alias are also routed to the target keyspace at this point.
for _, ks := range []string{sourceKeyspace, sourceAliasKeyspace, targetKeyspace} {
lastIndex = insertRows(lastIndex, ks)
}
// Note: here we have already switched, and we can insert into the target keyspace, and it should get reverse
// replicated to the source keyspace. The source keyspace is routed to the target keyspace at this point.
lastIndex = insertRows(lastIndex, sourceKeyspace)
mt.Complete()
require.Zero(t, len(getKeyspaceRoutingRules(t, vc).Rules))
actualRowsInserted := getRowCount(t, vtgateConn, fmt.Sprintf("%s.%s", targetKeyspace, "t1"))
log.Infof("Migration completed, total rows in target: %d", actualRowsInserted)
require.Equal(t, lastIndex, int64(actualRowsInserted))
}

// If switched queries with source/alias qualifiers should execute on target, else on source. Confirm that
// If switched, queries with source qualifiers should execute on target, else on source. Confirm that
// the routing rules are as expected and that the query executes on the expected tablet.
func validateKeyspaceRoutingRules(t *testing.T, vc *VitessCluster, primaries map[string]*cluster.VttabletProcess, rulesMap map[string]*vschemapb.KeyspaceRoutingRules, switched bool) {
currentRules := getKeyspaceRoutingRules(t, vc)
Expand All @@ -224,25 +215,19 @@ func validateKeyspaceRoutingRules(t *testing.T, vc *VitessCluster, primaries map
require.ElementsMatch(t, rulesMap["post"].Rules, currentRules.Rules)
validateQueryRoute("mt", "target")
validateQueryRoute("s1", "target")
validateQueryRoute("a1", "target")
} else {
require.ElementsMatch(t, rulesMap["pre"].Rules, currentRules.Rules)
// Note that with multi-tenant migration, we cannot redirect the target keyspace since
// there are multiple source keyspaces and the target has the aggregate of all the tenants.
validateQueryRoute("mt", "target")
validateQueryRoute("s1", "source")
validateQueryRoute("a1", "source")
}
}

func getSourceKeyspace(tenantId int64) string {
return fmt.Sprintf(sourceKeyspaceTemplate, tenantId)
}

func getSourceAliasKeyspace(tenantId int64) string {
return fmt.Sprintf(sourceAliasKeyspaceTemplate, tenantId)
}

func (mtm *multiTenantMigration) insertSomeData(t *testing.T, tenantId int64, keyspace string, numRows int64) {
vtgateConn, closeConn := getVTGateConn()
defer closeConn()
Expand Down Expand Up @@ -362,7 +347,7 @@ func (mtm *multiTenantMigration) getLastID(tenantId int64) int64 {
return mtm.lastIDs[tenantId]
}

func (mtm *multiTenantMigration) initTenantData(t *testing.T, tenantId int64, sourceAliasKeyspace string) {
func (mtm *multiTenantMigration) initTenantData(t *testing.T, tenantId int64) {
mtm.insertSomeData(t, tenantId, getSourceKeyspace(tenantId), numInitialRowsPerTenant)
}

Expand All @@ -374,16 +359,14 @@ func (mtm *multiTenantMigration) setup(tenantId int64) {
log.Infof("Creating MoveTables for tenant %d", tenantId)
mtm.setLastID(tenantId, 0)
sourceKeyspace := getSourceKeyspace(tenantId)
sourceAliasKeyspace := getSourceAliasKeyspace(tenantId)
_, err := vc.AddKeyspace(mtm.t, []*Cell{vc.Cells["zone1"]}, sourceKeyspace, "0", stVSchema, stSchema,
1, 0, getInitialTabletIdForTenant(tenantId), nil)
require.NoError(mtm.t, err)
mtm.initTenantData(mtm.t, tenantId, sourceAliasKeyspace)
mtm.initTenantData(mtm.t, tenantId)
}

func (mtm *multiTenantMigration) start(tenantId int64) {
sourceKeyspace := getSourceKeyspace(tenantId)
sourceAliasKeyspace := getSourceAliasKeyspace(tenantId)
mtm.setTenantMigrationStatus(tenantId, tenantMigrationStatusMigrating)
mt := newVtctldMoveTables(&moveTablesWorkflow{
workflowInfo: &workflowInfo{
Expand All @@ -395,7 +378,6 @@ func (mtm *multiTenantMigration) start(tenantId int64) {
tables: mtm.tables,
createFlags: []string{
"--tenant-id", strconv.FormatInt(tenantId, 10),
"--source-keyspace-alias", sourceAliasKeyspace,
},
})
mtm.setActiveMoveTables(tenantId, mt)
Expand All @@ -404,13 +386,11 @@ func (mtm *multiTenantMigration) start(tenantId int64) {

func (mtm *multiTenantMigration) switchTraffic(tenantId int64) {
t := mtm.t
sourceAliasKeyspace := getSourceAliasKeyspace(tenantId)
sourceKeyspaceName := getSourceKeyspace(tenantId)
mt := mtm.getActiveMoveTables(tenantId)
ksWorkflow := fmt.Sprintf("%s.%s", mtm.targetKeyspace, mt.workflowName)
waitForWorkflowState(t, vc, ksWorkflow, binlogdatapb.VReplicationWorkflowState_Running.String())
// we intentionally insert first into the source alias keyspace and then the source keyspace to test routing rules for both.
mtm.insertSomeData(t, tenantId, sourceAliasKeyspace, numAdditionalRowsPerTenant)
mtm.insertSomeData(t, tenantId, sourceKeyspaceName, numAdditionalRowsPerTenant)
mt.SwitchReadsAndWrites()
mtm.insertSomeData(t, tenantId, sourceKeyspaceName, numAdditionalRowsPerTenant)
}
Expand Down
Loading
Loading