зеркало из https://github.com/github/vitess-gh.git
vtctl: CopySchemaShard optionally allows source shard instead of source
tablet as argument.
This commit is contained in:
Родитель
e8d8012ed2
Коммит
a30503ca0b
|
@ -315,8 +315,8 @@ var commands = []commandGroup{
|
|||
"[-force] {-sql=<sql> || -sql-file=<filename>} <keyspace>",
|
||||
"Applies the schema change to the specified keyspace on every master, running in parallel on all shards. The changes are then propagated to slaves via replication. If the force flag is set, then numerous checks will be ignored, so that option should be used very cautiously."},
|
||||
command{"CopySchemaShard", commandCopySchemaShard,
|
||||
"[-tables=<table1>,<table2>,...] [-exclude_tables=<table1>,<table2>,...] [-include-views] <source tablet alias> <destination keyspace/shard>",
|
||||
"Copies the schema from a source tablet to the specified shard. The schema is applied directly on the master of the destination shard, and it is propagated to the replicas through binlogs."},
|
||||
"[-tables=<table1>,<table2>,...] [-exclude_tables=<table1>,<table2>,...] [-include-views] {<source keyspace/shard> || <source tablet alias>} <destination keyspace/shard>",
|
||||
"Copies the schema from a source shard's master (or a specific tablet) to a destination shard. The schema is applied directly on the master of the destination shard, and it is propagated to the replicas through binlogs."},
|
||||
|
||||
command{"ValidateVersionShard", commandValidateVersionShard,
|
||||
"<keyspace/shard>",
|
||||
|
@ -1803,11 +1803,7 @@ func commandCopySchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags
|
|||
}
|
||||
|
||||
if subFlags.NArg() != 2 {
|
||||
return fmt.Errorf("The <tablet alias> and <keyspace/shard> arguments are both required for the CopySchemaShard command. The <tablet alias> argument identifies a source and the <keyspace/shard> argument identifies a destination.")
|
||||
}
|
||||
tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("The <source keyspace/shard> and <destination keyspace/shard> arguments are both required for the CopySchemaShard command. Instead of the <source keyspace/shard> argument, you can also specify <tablet alias> which refers to a specific tablet of the shard in the source keyspace.")
|
||||
}
|
||||
var tableArray []string
|
||||
if *tables != "" {
|
||||
|
@ -1817,13 +1813,21 @@ func commandCopySchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags
|
|||
if *excludeTables != "" {
|
||||
excludeTableArray = strings.Split(*excludeTables, ",")
|
||||
}
|
||||
|
||||
keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(1))
|
||||
destKeyspace, destShard, err := topo.ParseKeyspaceShardString(subFlags.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return wr.CopySchemaShard(ctx, tabletAlias, tableArray, excludeTableArray, *includeViews, keyspace, shard)
|
||||
sourceKeyspace, sourceShard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
|
||||
if err == nil {
|
||||
return wr.CopySchemaShardFromShard(ctx, tableArray, excludeTableArray, *includeViews, sourceKeyspace, sourceShard, destKeyspace, destShard)
|
||||
} else {
|
||||
sourceTabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(0))
|
||||
if err == nil {
|
||||
return wr.CopySchemaShard(ctx, sourceTabletAlias, tableArray, excludeTableArray, *includeViews, destKeyspace, destShard)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func commandValidateVersionShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
|
||||
|
|
|
@ -417,27 +417,38 @@ func (wr *Wrangler) ApplySchemaKeyspace(ctx context.Context, keyspace string, ch
|
|||
return nil, wr.unlockKeyspace(ctx, keyspace, actionNode, lockPath, err)
|
||||
}
|
||||
|
||||
// CopySchemaShardFromShard copies the schema from a source shard to the specified destination shard.
|
||||
// For both source and destination it picks the master tablet. See also CopySchemaShard.
|
||||
func (wr *Wrangler) CopySchemaShardFromShard(ctx context.Context, tables, excludeTables []string, includeViews bool, sourceKeyspace, sourceShard, destKeyspace, destShard string) error {
|
||||
sourceShardInfo, err := wr.ts.GetShard(ctx, sourceKeyspace, sourceShard)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return wr.CopySchemaShard(ctx, sourceShardInfo.MasterAlias, tables, excludeTables, includeViews, destKeyspace, destShard)
|
||||
}
|
||||
|
||||
// CopySchemaShard copies the schema from a source tablet to the
|
||||
// specified shard. The schema is applied directly on the master of
|
||||
// the destination shard, and is propogated to the replicas through
|
||||
// binlogs.
|
||||
func (wr *Wrangler) CopySchemaShard(ctx context.Context, srcTabletAlias topo.TabletAlias, tables, excludeTables []string, includeViews bool, keyspace, shard string) error {
|
||||
func (wr *Wrangler) CopySchemaShard(ctx context.Context, srcTabletAlias topo.TabletAlias, tables, excludeTables []string, includeViews bool, destKeyspace, destShard string) error {
|
||||
sd, err := wr.GetSchema(ctx, srcTabletAlias, tables, excludeTables, includeViews)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shardInfo, err := wr.ts.GetShard(ctx, keyspace, shard)
|
||||
destShardInfo, err := wr.ts.GetShard(ctx, destKeyspace, destShard)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tabletInfo, err := wr.ts.GetTablet(ctx, shardInfo.MasterAlias)
|
||||
destTabletInfo, err := wr.ts.GetTablet(ctx, destShardInfo.MasterAlias)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
createSql := sd.ToSQLStrings()
|
||||
|
||||
for i, sqlLine := range createSql {
|
||||
err = wr.applySqlShard(ctx, tabletInfo, sqlLine, i == len(createSql)-1)
|
||||
err = wr.applySqlShard(ctx, destTabletInfo, sqlLine, i == len(createSql)-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -90,7 +90,15 @@ func (fpc *FakePoolConnection) Reconnect() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func TestCopySchemaShard(t *testing.T) {
|
||||
func TestCopySchemaShard_UseTabletAsSource(t *testing.T) {
|
||||
copySchema(t, false /* useShardAsSource */)
|
||||
}
|
||||
|
||||
func TestCopySchemaShard_UseShardAsSource(t *testing.T) {
|
||||
copySchema(t, true /* useShardAsSource */)
|
||||
}
|
||||
|
||||
func copySchema(t *testing.T, useShardAsSource bool) {
|
||||
db := fakesqldb.Register()
|
||||
ts := zktopo.NewTestServer(t, []string{"cell1", "cell2"})
|
||||
wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient(), time.Second)
|
||||
|
@ -110,7 +118,7 @@ func TestCopySchemaShard(t *testing.T) {
|
|||
defer ft.StopActionLoop(t)
|
||||
}
|
||||
|
||||
sourceRdonly.FakeMysqlDaemon.Schema = &myproto.SchemaDefinition{
|
||||
schema := &myproto.SchemaDefinition{
|
||||
DatabaseSchema: "CREATE DATABASE `{{.DatabaseName}}` /*!40100 DEFAULT CHARACTER SET utf8 */",
|
||||
TableDefinitions: []*myproto.TableDefinition{
|
||||
&myproto.TableDefinition{
|
||||
|
@ -125,6 +133,8 @@ func TestCopySchemaShard(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
sourceMaster.FakeMysqlDaemon.Schema = schema
|
||||
sourceRdonly.FakeMysqlDaemon.Schema = schema
|
||||
|
||||
createDb := "CREATE DATABASE `vt_ks` /*!40100 DEFAULT CHARACTER SET utf8 */"
|
||||
createTable := "CREATE TABLE `vt_ks`.`resharding1` (\n"+
|
||||
|
@ -146,7 +156,11 @@ func TestCopySchemaShard(t *testing.T) {
|
|||
db.AddQuery(createTable, &mproto.QueryResult{})
|
||||
db.AddQuery(createTableView, &mproto.QueryResult{})
|
||||
|
||||
if err := vp.Run([]string{"CopySchemaShard", "-include-views", sourceRdonly.Tablet.Alias.String(), "ks/-40"}); err != nil {
|
||||
source := sourceRdonly.Tablet.Alias.String()
|
||||
if useShardAsSource {
|
||||
source = "ks/-80"
|
||||
}
|
||||
if err := vp.Run([]string{"CopySchemaShard", "-include-views", source, "ks/-40"}); err != nil {
|
||||
t.Fatalf("CopySchemaShard failed: %v", err)
|
||||
}
|
||||
if count := db.GetQueryCalledNum(createDb); count != 1 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче