Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
Merge pull request vitessio#6216 from tinyspeck/fixes-issue-with-vali…
Browse files Browse the repository at this point in the history
…date-keyspace

Allow empty shards when validating schemas
  • Loading branch information
rafael authored Jun 2, 2020
2 parents 1f53471 + c6c59ee commit 19fdf8b
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 35 deletions.
5 changes: 3 additions & 2 deletions go/vt/vtctl/vtctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ var commands = []commandGroup{
"[-exclude_tables=''] [-include-views] <keyspace/shard>",
"Validates that the master schema matches all of the slaves."},
{"ValidateSchemaKeyspace", commandValidateSchemaKeyspace,
"[-exclude_tables=''] [-include-views] <keyspace name>",
"[-exclude_tables=''] [-include-views] [-skip-no-master] <keyspace name>",
"Validates that the master schema from shard 0 matches the schema on all of the other tablets in the keyspace."},
{"ApplySchema", commandApplySchema,
"[-allow_long_unavailability] [-wait_slave_timeout=10s] {-sql=<sql> || -sql-file=<filename>} <keyspace>",
Expand Down Expand Up @@ -2350,6 +2350,7 @@ func commandValidateSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subF
func commandValidateSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/")
includeViews := subFlags.Bool("include-views", false, "Includes views in the validation")
skipNoMaster := subFlags.Bool("skip-no-master", false, "Skip shards that don't have master when performing validation")
if err := subFlags.Parse(args); err != nil {
return err
}
Expand All @@ -2362,7 +2363,7 @@ func commandValidateSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, s
if *excludeTables != "" {
excludeTableArray = strings.Split(*excludeTables, ",")
}
return wr.ValidateSchemaKeyspace(ctx, keyspace, excludeTableArray, *includeViews)
return wr.ValidateSchemaKeyspace(ctx, keyspace, excludeTableArray, *includeViews, *skipNoMaster)
}

func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtctld/vtctld.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func InitVtctld(ts *topo.Server) {

actionRepo.RegisterKeyspaceAction("ValidateSchemaKeyspace",
func(ctx context.Context, wr *wrangler.Wrangler, keyspace string, r *http.Request) (string, error) {
return "", wr.ValidateSchemaKeyspace(ctx, keyspace, nil, false)
return "", wr.ValidateSchemaKeyspace(ctx, keyspace, nil, false, false)
})

actionRepo.RegisterKeyspaceAction("ValidateVersionKeyspace",
Expand Down
52 changes: 20 additions & 32 deletions go/vt/wrangler/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func (wr *Wrangler) ValidateSchemaShard(ctx context.Context, keyspace, shard str

// ValidateSchemaKeyspace will diff the schema from all the tablets in
// the keyspace.
func (wr *Wrangler) ValidateSchemaKeyspace(ctx context.Context, keyspace string, excludeTables []string, includeViews bool) error {
func (wr *Wrangler) ValidateSchemaKeyspace(ctx context.Context, keyspace string, excludeTables []string, includeViews, skipNoMaster bool) error {
// find all the shards
shards, err := wr.ts.GetShardNames(ctx, keyspace)
if err != nil {
Expand All @@ -202,60 +202,48 @@ func (wr *Wrangler) ValidateSchemaKeyspace(ctx context.Context, keyspace string,
return wr.ValidateSchemaShard(ctx, keyspace, shards[0], excludeTables, includeViews)
}

// find the reference schema using the first shard's master
si, err := wr.ts.GetShard(ctx, keyspace, shards[0])
if err != nil {
return fmt.Errorf("GetShard(%v, %v) failed: %v", keyspace, shards[0], err)
}
if !si.HasMaster() {
return fmt.Errorf("no master in shard %v/%v", keyspace, shards[0])
}
referenceAlias := si.MasterAlias
log.Infof("Gathering schema for reference master %v", topoproto.TabletAliasString(referenceAlias))
referenceSchema, err := wr.GetSchema(ctx, referenceAlias, nil, excludeTables, includeViews)
if err != nil {
return fmt.Errorf("GetSchema(%v, nil, %v, %v) failed: %v", referenceAlias, excludeTables, includeViews, err)
}
var referenceSchema *tabletmanagerdatapb.SchemaDefinition
var referenceAlias *topodatapb.TabletAlias

// then diff with all other tablets everywhere
er := concurrency.AllErrorRecorder{}
wg := sync.WaitGroup{}

// first diff the slaves in the reference shard 0
aliases, err := wr.ts.FindAllTabletAliasesInShard(ctx, keyspace, shards[0])
if err != nil {
return fmt.Errorf("FindAllTabletAliasesInShard(%v, %v) failed: %v", keyspace, shards[0], err)
}

for _, alias := range aliases {
if topoproto.TabletAliasEqual(alias, si.MasterAlias) {
continue
}

wg.Add(1)
go wr.diffSchema(ctx, referenceSchema, referenceAlias, alias, excludeTables, includeViews, &wg, &er)
}

// then diffs all tablets in the other shards
for _, shard := range shards[1:] {
for _, shard := range shards[0:] {
si, err := wr.ts.GetShard(ctx, keyspace, shard)
if err != nil {
er.RecordError(fmt.Errorf("GetShard(%v, %v) failed: %v", keyspace, shard, err))
continue
}

if !si.HasMaster() {
er.RecordError(fmt.Errorf("no master in shard %v/%v", keyspace, shard))
if !skipNoMaster {
er.RecordError(fmt.Errorf("no master in shard %v/%v", keyspace, shard))
}
continue
}

if referenceSchema == nil {
referenceAlias = si.MasterAlias
log.Infof("Gathering schema for reference master %v", topoproto.TabletAliasString(referenceAlias))
referenceSchema, err = wr.GetSchema(ctx, referenceAlias, nil, excludeTables, includeViews)
if err != nil {
return fmt.Errorf("GetSchema(%v, nil, %v, %v) failed: %v", referenceAlias, excludeTables, includeViews, err)
}
}

aliases, err := wr.ts.FindAllTabletAliasesInShard(ctx, keyspace, shard)
if err != nil {
er.RecordError(fmt.Errorf("FindAllTabletAliasesInShard(%v, %v) failed: %v", keyspace, shard, err))
continue
}

for _, alias := range aliases {
// Don't diff schemas for self
if referenceAlias == alias {
continue
}
wg.Add(1)
go wr.diffSchema(ctx, referenceSchema, referenceAlias, alias, excludeTables, includeViews, &wg, &er)
}
Expand Down

0 comments on commit 19fdf8b

Please sign in to comment.