-
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
Materialize: Only get schema from source tablets if target is missing tables #6601
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -50,6 +50,7 @@ type materializer struct { | |||||
targetVSchema *vindexes.KeyspaceSchema | ||||||
sourceShards []*topo.ShardInfo | ||||||
targetShards []*topo.ShardInfo | ||||||
mu sync.Mutex | ||||||
} | ||||||
|
||||||
const ( | ||||||
|
@@ -589,51 +590,55 @@ func (wr *Wrangler) buildMaterializer(ctx context.Context, ms *vtctldatapb.Mater | |||||
}, nil | ||||||
} | ||||||
|
||||||
func (mz *materializer) getTableDDLs(ctx context.Context) (map[string]string, error) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function should run only once per invocation, and all others should use the result: it should populate a new Using |
||||||
tableDDLs := make(map[string]string) | ||||||
allTables := []string{"/.*/"} | ||||||
|
||||||
sourceMaster := mz.sourceShards[0].MasterAlias | ||||||
if sourceMaster == nil { | ||||||
return nil, fmt.Errorf("source shard must have a master for copying schema: %v", mz.sourceShards[0].ShardName()) | ||||||
} | ||||||
|
||||||
log.Infof("getting table schemas from source master %v...", sourceMaster) | ||||||
var err error | ||||||
sourceSchema, err := mz.wr.GetSchema(ctx, sourceMaster, allTables, nil, false) | ||||||
if err != nil { | ||||||
return nil, err | ||||||
} | ||||||
log.Infof("got table schemas from source master %v.", sourceMaster) | ||||||
|
||||||
for _, td := range sourceSchema.TableDefinitions { | ||||||
tableDDLs[td.Name] = td.Schema | ||||||
} | ||||||
return tableDDLs, nil | ||||||
} | ||||||
|
||||||
func (mz *materializer) deploySchema(ctx context.Context) error { | ||||||
var tableDDLs map[string]string | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
i think it's clearer that it's from the source, hence the name |
||||||
|
||||||
return mz.forAllTargets(func(target *topo.ShardInfo) error { | ||||||
allTables := []string{"/.*/"} | ||||||
|
||||||
hasTargetTable := map[string]bool{} | ||||||
{ | ||||||
log.Infof("getting table schemas from target master %v...", target.MasterAlias) | ||||||
targetSchema, err := mz.wr.GetSchema(ctx, target.MasterAlias, allTables, nil, false) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
log.Infof("got table schemas from target master %v.", target.MasterAlias) | ||||||
|
||||||
for _, td := range targetSchema.TableDefinitions { | ||||||
hasTargetTable[td.Name] = true | ||||||
} | ||||||
log.Infof("getting table schemas from target master %v...", target.MasterAlias) | ||||||
targetSchema, err := mz.wr.GetSchema(ctx, target.MasterAlias, allTables, nil, false) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
log.Infof("got table schemas from target master %v.", target.MasterAlias) | ||||||
|
||||||
sourceDDL := map[string]string{} | ||||||
{ | ||||||
sourceMaster := mz.sourceShards[0].MasterAlias | ||||||
if sourceMaster == nil { | ||||||
return fmt.Errorf("source shard must have a master for copying schema: %v", mz.sourceShards[0].ShardName()) | ||||||
} | ||||||
|
||||||
log.Infof("getting table schemas from source master %v...", sourceMaster) | ||||||
var err error | ||||||
sourceSchema, err := mz.wr.GetSchema(ctx, sourceMaster, allTables, nil, false) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
log.Infof("got table schemas from source master %v.", sourceMaster) | ||||||
|
||||||
for _, td := range sourceSchema.TableDefinitions { | ||||||
sourceDDL[td.Name] = td.Schema | ||||||
} | ||||||
for _, td := range targetSchema.TableDefinitions { | ||||||
hasTargetTable[td.Name] = true | ||||||
} | ||||||
|
||||||
targetTablet, err := mz.wr.ts.GetTablet(ctx, target.MasterAlias) | ||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
applyDDLs := []string{} | ||||||
var applyDDLs []string | ||||||
{ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this an empty clause? |
||||||
} | ||||||
for _, ts := range mz.ms.TableSettings { | ||||||
if hasTargetTable[ts.TargetTable] { | ||||||
// Table already exists. | ||||||
|
@@ -642,6 +647,21 @@ func (mz *materializer) deploySchema(ctx context.Context) error { | |||||
if ts.CreateDdl == "" { | ||||||
return fmt.Errorf("target table %v does not exist and there is no create ddl defined", ts.TargetTable) | ||||||
} | ||||||
|
||||||
var err error | ||||||
mz.mu.Lock() | ||||||
if len(tableDDLs) == 0 { | ||||||
//only get ddls for tables, once and lazily: if we need to copy the schema from source to target | ||||||
//we copy schemas from masters on the source keyspace | ||||||
//and we have found use cases where user just has a replica (no master) in the source keyspace | ||||||
tableDDLs, err = mz.getTableDDLs(ctx) | ||||||
} | ||||||
mz.mu.Unlock() | ||||||
if err != nil { | ||||||
log.Errorf("Error getting DDLs of source tables: %s", err.Error()) | ||||||
return err | ||||||
} | ||||||
|
||||||
createDDL := ts.CreateDdl | ||||||
if createDDL == createDDLAsCopy || createDDL == createDDLAsCopyDropConstraint { | ||||||
if ts.SourceExpression != "" { | ||||||
|
@@ -656,7 +676,7 @@ func (mz *materializer) deploySchema(ctx context.Context) error { | |||||
} | ||||||
} | ||||||
|
||||||
ddl, ok := sourceDDL[ts.TargetTable] | ||||||
ddl, ok := tableDDLs[ts.TargetTable] | ||||||
if !ok { | ||||||
return fmt.Errorf("source table %v does not exist", ts.TargetTable) | ||||||
} | ||||||
|
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.
optional, but wanna mention why this mutex exists? it's not really protecting anything inside the materializer right? i think it's protecting the getting of the getTableDDLs? and is that only an optimization? if so, does it make sense to just have it inside the deploy?
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 think this mutex is needed, but for a different reason, given below.