Skip to content
This repository was archived by the owner on Dec 16, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions go/vt/vtctl/vtctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,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 @@ -2256,6 +2256,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 @@ -2268,7 +2269,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