Skip to content

Commit 0b8e500

Browse files
committed
ReloadSchema{Shard,Keyspace} and UI fixes.
- Adding vtctl ReloadSchema{Shard,Keyspace} commands. - Adding ReloadSchema{Shard,Keyspace} to ui. - Removing test workflow data to avoid flickering at startup. - Fixing schema display in vtctld2 UI. - Rebuild vtctl doc. - Rebuilding UI.
1 parent 5babf50 commit 0b8e500

18 files changed

+228
-229
lines changed

doc/vtctlReference.md

+52
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,8 @@ Updates the configuration of the MaxReplicationLag module. The configuration mus
10731073
* [GetVSchema](#getvschema)
10741074
* [RebuildVSchemaGraph](#rebuildvschemagraph)
10751075
* [ReloadSchema](#reloadschema)
1076+
* [ReloadSchemaKeyspace](#reloadschemakeyspace)
1077+
* [ReloadSchemaShard](#reloadschemashard)
10761078
* [ValidatePermissionsKeyspace](#validatepermissionskeyspace)
10771079
* [ValidatePermissionsShard](#validatepermissionsshard)
10781080
* [ValidateSchemaKeyspace](#validateschemakeyspace)
@@ -1261,6 +1263,56 @@ Reloads the schema on a remote tablet.
12611263
* the <code>&lt;tablet alias&gt;</code> argument is required for the <code>&lt;ReloadSchema&gt;</code> command This error occurs if the command is not called with exactly one argument.
12621264

12631265

1266+
### ReloadSchemaKeyspace
1267+
1268+
Reloads the schema on all the tablets in a keyspace.
1269+
1270+
#### Example
1271+
1272+
<pre class="command-example">ReloadSchemaKeyspace [-concurrency=10] [-include_master=false] &lt;keyspace&gt;</pre>
1273+
1274+
#### Flags
1275+
1276+
| Name | Type | Definition |
1277+
| :-------- | :--------- | :--------- |
1278+
| concurrency | Int | How many tablets to reload in parallel |
1279+
| include_master | Boolean | Include the master tablet(s) |
1280+
1281+
1282+
#### Arguments
1283+
1284+
* <code>&lt;keyspace&gt;</code> &ndash; Required. The name of a sharded database that contains one or more tables. Vitess distributes keyspace shards into multiple machines and provides an SQL interface to query the data. The argument value must be a string that does not contain whitespace.
1285+
1286+
#### Errors
1287+
1288+
* the <code>&lt;keyspace&gt;</code> argument is required for the <code>&lt;ReloadSchemaKeyspace&gt;</code> command This error occurs if the command is not called with exactly one argument.
1289+
1290+
1291+
### ReloadSchemaShard
1292+
1293+
Reloads the schema on all the tablets in a shard.
1294+
1295+
#### Example
1296+
1297+
<pre class="command-example">ReloadSchemaShard [-concurrency=10] [-include_master=false] &lt;keyspace/shard&gt;</pre>
1298+
1299+
#### Flags
1300+
1301+
| Name | Type | Definition |
1302+
| :-------- | :--------- | :--------- |
1303+
| concurrency | Int | How many tablets to reload in parallel |
1304+
| include_master | Boolean | Include the master tablet |
1305+
1306+
1307+
#### Arguments
1308+
1309+
* <code>&lt;keyspace/shard&gt;</code> &ndash; Required. The name of a sharded database that contains one or more tables as well as the shard associated with the command. The keyspace must be identified by a string that does not contain whitepace, while the shard is typically identified by a string in the format <code>&lt;range start&gt;-&lt;range end&gt;</code>.
1310+
1311+
#### Errors
1312+
1313+
* the <code>&lt;keyspace/shard&gt;</code> argument is required for the <code>&lt;ReloadSchemaShard&gt;</code> command This error occurs if the command is not called with exactly one argument.
1314+
1315+
12641316
### ValidatePermissionsKeyspace
12651317

12661318
Validates that the master permissions from shard 0 match those of all of the other tablets in the keyspace.

go/vt/schemamanager/tablet_executor.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"golang.org/x/net/context"
1313

14+
"github.com/youtube/vitess/go/sync2"
1415
"github.com/youtube/vitess/go/vt/mysqlctl/tmutils"
1516
"github.com/youtube/vitess/go/vt/sqlparser"
1617
"github.com/youtube/vitess/go/vt/wrangler"
@@ -179,7 +180,7 @@ func (exec *TabletExecutor) preflightSchemaChanges(ctx context.Context, sqls []s
179180
// DROP IF EXISTS on a nonexistent table does not change the schema. It's safe to ignore.
180181
continue
181182
}
182-
return fmt.Errorf("Schema change: '%s' does not introduce any table definition change.", sqls[i])
183+
return fmt.Errorf("schema change: '%s' does not introduce any table definition change", sqls[i])
183184
}
184185
}
185186
exec.schemaDiffs = schemaDiffs
@@ -261,13 +262,14 @@ func (exec *TabletExecutor) executeOnAllTablets(ctx context.Context, execResult
261262
// If all shards succeeded, wait (up to waitSlaveTimeout) for slaves to
262263
// execute the schema change via replication. This is best-effort, meaning
263264
// we still return overall success if the timeout expires.
265+
concurrency := sync2.NewSemaphore(10, 0)
264266
reloadCtx, cancel := context.WithTimeout(ctx, exec.waitSlaveTimeout)
265267
defer cancel()
266268
for _, result := range execResult.SuccessShards {
267269
wg.Add(1)
268270
go func(result ShardResult) {
269271
defer wg.Done()
270-
exec.wr.ReloadSchemaShard(reloadCtx, exec.keyspace, result.Shard, result.Position)
272+
exec.wr.ReloadSchemaShard(reloadCtx, exec.keyspace, result.Shard, result.Position, concurrency, false /* includeMaster */)
271273
}(result)
272274
}
273275
wg.Wait()

go/vt/vtctl/vtctl.go

+38
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ import (
9595
"github.com/youtube/vitess/go/flagutil"
9696
"github.com/youtube/vitess/go/mysqlconn/replication"
9797
"github.com/youtube/vitess/go/sqltypes"
98+
"github.com/youtube/vitess/go/sync2"
9899
hk "github.com/youtube/vitess/go/vt/hook"
99100
"github.com/youtube/vitess/go/vt/key"
100101
"github.com/youtube/vitess/go/vt/logutil"
@@ -323,6 +324,12 @@ var commands = []commandGroup{
323324
{"ReloadSchema", commandReloadSchema,
324325
"<tablet alias>",
325326
"Reloads the schema on a remote tablet."},
327+
{"ReloadSchemaShard", commandReloadSchemaShard,
328+
"[-concurrency=10] [-include_master=false] <keyspace/shard>",
329+
"Reloads the schema on all the tablets in a shard."},
330+
{"ReloadSchemaKeyspace", commandReloadSchemaKeyspace,
331+
"[-concurrency=10] [-include_master=false] <keyspace>",
332+
"Reloads the schema on all the tablets in a keyspace."},
326333
{"ValidateSchemaShard", commandValidateSchemaShard,
327334
"[-exclude_tables=''] [-include-views] <keyspace/shard>",
328335
"Validates that the master schema matches all of the slaves."},
@@ -1785,6 +1792,37 @@ func commandReloadSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *f
17851792
return wr.ReloadSchema(ctx, tabletAlias)
17861793
}
17871794

1795+
func commandReloadSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
1796+
concurrency := subFlags.Int("concurrency", 10, "How many tablets to reload in parallel")
1797+
includeMaster := subFlags.Bool("include_master", true, "Include the master tablet")
1798+
if err := subFlags.Parse(args); err != nil {
1799+
return err
1800+
}
1801+
if subFlags.NArg() != 1 {
1802+
return fmt.Errorf("the <keyspace/shard> argument is required for the ReloadSchemaShard command")
1803+
}
1804+
keyspace, shard, err := topoproto.ParseKeyspaceShard(subFlags.Arg(0))
1805+
if err != nil {
1806+
return err
1807+
}
1808+
sema := sync2.NewSemaphore(*concurrency, 0)
1809+
wr.ReloadSchemaShard(ctx, keyspace, shard, "" /* waitPosition */, sema, *includeMaster)
1810+
return nil
1811+
}
1812+
1813+
func commandReloadSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
1814+
concurrency := subFlags.Int("concurrency", 10, "How many tablets to reload in parallel")
1815+
includeMaster := subFlags.Bool("include_master", true, "Include the master tablet(s)")
1816+
if err := subFlags.Parse(args); err != nil {
1817+
return err
1818+
}
1819+
if subFlags.NArg() != 1 {
1820+
return fmt.Errorf("the <keyspace> argument is required for the ReloadSchemaKeyspace command")
1821+
}
1822+
sema := sync2.NewSemaphore(*concurrency, 0)
1823+
return wr.ReloadSchemaKeyspace(ctx, subFlags.Arg(0), sema, *includeMaster)
1824+
}
1825+
17881826
func commandValidateSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
17891827
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/")
17901828
includeViews := subFlags.Bool("include-views", false, "Includes views in the validation")

go/vt/wrangler/schema.go

+36-15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
log "github.com/golang/glog"
1818
"github.com/youtube/vitess/go/sqltypes"
19+
"github.com/youtube/vitess/go/sync2"
1920
"github.com/youtube/vitess/go/vt/concurrency"
2021
"github.com/youtube/vitess/go/vt/mysqlctl/tmutils"
2122
"github.com/youtube/vitess/go/vt/topo"
@@ -56,31 +57,35 @@ func (wr *Wrangler) ReloadSchema(ctx context.Context, tabletAlias *topodatapb.Ta
5657
// and the periodic schema reload makes them self-healing anyway.
5758
// So we do this on a best-effort basis, and log warnings for any tablets
5859
// that fail to reload within the context deadline.
59-
// Note that this skips the master because it's assumed that the schema
60-
// was reloaded there right after applying it.
61-
func (wr *Wrangler) ReloadSchemaShard(ctx context.Context, keyspace, shard, replicationPos string) {
60+
func (wr *Wrangler) ReloadSchemaShard(ctx context.Context, keyspace, shard, replicationPos string, concurrency *sync2.Semaphore, includeMaster bool) {
6261
tablets, err := wr.ts.GetTabletMapForShard(ctx, keyspace, shard)
63-
if err != nil {
64-
if err != topo.ErrPartialResult {
65-
// This is best-effort, so just log it and move on.
66-
wr.logger.Warningf("Failed to reload schema on slave tablets in %v/%v (use vtctl ReloadSchema to fix individual tablets): %v", keyspace, shard, err)
67-
return
68-
}
69-
// We got a partial result. Do what we can, but warn that some may be missed.
70-
wr.logger.Warningf("Failed to fetch all tablets for %v/%v. Some slave tablets may not have schema reloaded (use vtctl ReloadSchema to fix individual tablets)", keyspace, shard)
62+
switch err {
63+
case topo.ErrPartialResult:
64+
// We got a partial result. Do what we can, but warn
65+
// that some may be missed.
66+
wr.logger.Warningf("ReloadSchemaShard(%v/%v) got a partial tablet list. Some tablets may not have schema reloaded (use vtctl ReloadSchema to fix individual tablets)", keyspace, shard)
67+
case nil:
68+
// Good case, keep going too.
69+
default:
70+
// This is best-effort, so just log it and move on.
71+
wr.logger.Warningf("ReloadSchemaShard(%v/%v) failed to load tablet list, will not reload schema (use vtctl ReloadSchemaShard to try again): %v", keyspace, shard, err)
72+
return
7173
}
7274

7375
var wg sync.WaitGroup
7476
for _, ti := range tablets {
75-
if ti.Type == topodatapb.TabletType_MASTER {
76-
// We don't need to reload on the master because we assume
77-
// ExecuteFetchAsDba() already did that.
77+
if !includeMaster && ti.Type == topodatapb.TabletType_MASTER {
78+
// We don't need to reload on the master
79+
// because we assume ExecuteFetchAsDba()
80+
// already did that.
7881
continue
7982
}
8083

8184
wg.Add(1)
8285
go func(tablet *topodatapb.Tablet) {
8386
defer wg.Done()
87+
concurrency.Acquire()
88+
defer concurrency.Release()
8489
if err := wr.tmc.ReloadSchema(ctx, tablet, replicationPos); err != nil {
8590
wr.logger.Warningf(
8691
"Failed to reload schema on slave tablet %v in %v/%v (use vtctl ReloadSchema to try again): %v",
@@ -91,6 +96,21 @@ func (wr *Wrangler) ReloadSchemaShard(ctx context.Context, keyspace, shard, repl
9196
wg.Wait()
9297
}
9398

99+
// ReloadSchemaKeyspace reloads the schema in all shards in a
100+
// keyspace. The concurrency is shared across all shards (only that
101+
// many tablets will be reloaded at once).
102+
func (wr *Wrangler) ReloadSchemaKeyspace(ctx context.Context, keyspace string, concurrency *sync2.Semaphore, includeMaster bool) error {
103+
shards, err := wr.ts.GetShardNames(ctx, keyspace)
104+
if err != nil {
105+
return err
106+
}
107+
108+
for _, shard := range shards {
109+
wr.ReloadSchemaShard(ctx, keyspace, shard, "" /* waitPosition */, concurrency, includeMaster)
110+
}
111+
return nil
112+
}
113+
94114
// helper method to asynchronously diff a schema
95115
func (wr *Wrangler) diffSchema(ctx context.Context, masterSchema *tabletmanagerdatapb.SchemaDefinition, masterTabletAlias, alias *topodatapb.TabletAlias, excludeTables []string, includeViews bool, wg *sync.WaitGroup, er concurrency.ErrorRecorder) {
96116
defer wg.Done()
@@ -321,9 +341,10 @@ func (wr *Wrangler) CopySchemaShard(ctx context.Context, sourceTabletAlias *topo
321341
}
322342

323343
// Notify slaves to reload schema. This is best-effort.
344+
concurrency := sync2.NewSemaphore(10, 0)
324345
reloadCtx, cancel := context.WithTimeout(ctx, waitSlaveTimeout)
325346
defer cancel()
326-
wr.ReloadSchemaShard(reloadCtx, destKeyspace, destShard, destMasterPos)
347+
wr.ReloadSchemaShard(reloadCtx, destKeyspace, destShard, destMasterPos, concurrency, true /* includeMaster */)
327348
return nil
328349
}
329350

test/cache_invalidation.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ def setUpModule():
8484
master_tablet.mquery('vt_test_keyspace', _create_vt_a)
8585
master_tablet.mquery('vt_test_keyspace', _create_vt_b)
8686

87-
utils.run_vtctl(['ReloadSchema', master_tablet.tablet_alias])
88-
utils.run_vtctl(['ReloadSchema', replica_tablet.tablet_alias])
87+
utils.run_vtctl(['ReloadSchemaShard', 'test_keyspace/0'])
8988
utils.run_vtctl(['RebuildVSchemaGraph'])
9089

9190
utils.VtGate().start(tablets=[master_tablet, replica_tablet])

test/update_stream.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ def setUpModule():
9797
master_tablet.mquery('vt_test_keyspace', _create_vt_a)
9898
master_tablet.mquery('vt_test_keyspace', _create_vt_b)
9999

100-
utils.run_vtctl(['ReloadSchema', master_tablet.tablet_alias])
101-
utils.run_vtctl(['ReloadSchema', replica_tablet.tablet_alias])
100+
utils.run_vtctl(['ReloadSchemaKeyspace', 'test_keyspace'])
102101
utils.run_vtctl(['RebuildVSchemaGraph'])
103102

104103
utils.VtGate().start(tablets=[master_tablet, replica_tablet])

web/vtctld2/app/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@
2727
</head>
2828
<body class="flex-column">
2929
<vt-app-root class="flex-column flex-grow">Loading...</vt-app-root>
30-
<script type="text/javascript" src="inline.js"></script><script type="text/javascript" src="styles.07f8743f5392cfdfbcb5.bundle.js"></script><script type="text/javascript" src="main.7e82c61ecfeb791ebb7e.bundle.js"></script></body>
30+
<script type="text/javascript" src="inline.js"></script><script type="text/javascript" src="styles.07f8743f5392cfdfbcb5.bundle.js"></script><script type="text/javascript" src="main.bd7c386e52651518a1ce.bundle.js"></script></body>
3131
</html>

web/vtctld2/app/inline.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

web/vtctld2/app/main.7e82c61ecfeb791ebb7e.bundle.js renamed to web/vtctld2/app/main.bd7c386e52651518a1ce.bundle.js

+26-26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

web/vtctld2/src/app/dashboard/keyspace.component.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { DialogSettings } from '../shared/dialog/dialog-settings';
88
import { NewShardFlags } from '../shared/flags/shard.flags';
99
import { KeyspaceService } from '../api/keyspace.service';
1010
import { PrepareResponse } from '../shared/prepare-response';
11-
import { RebuildKeyspaceGraphFlags, RemoveKeyspaceCellFlags, ValidateKeyspaceFlags,
11+
import { RebuildKeyspaceGraphFlags, ReloadSchemaKeyspaceFlags,
12+
RemoveKeyspaceCellFlags, ValidateKeyspaceFlags,
1213
ValidateSchemaFlags, ValidateVersionFlags } from '../shared/flags/keyspace.flags';
1314
import { VtctlService } from '../api/vtctl.service';
1415

@@ -44,8 +45,9 @@ export class KeyspaceComponent implements OnInit, OnDestroy {
4445
{label: 'Validate Schema', command: (event) => {this.openValidateSchemaDialog(); }},
4546
{label: 'Validate Version', command: (event) => {this.openValidateVersionDialog(); }},
4647
]},
47-
{label: 'Rebuild', items: [
48+
{label: 'Rebuild / Reload', items: [
4849
{label: 'Rebuild Keyspace Graph', command: (event) => {this.openRebuildKeyspaceGraphDialog(); }},
50+
{label: 'Reload Schema in Keyspace', command: (event) => {this.openReloadSchemaKeyspaceDialog(); }},
4951
]},
5052
{label: 'Change', items: [
5153
{label: 'Remove Keyspace Cell', command: (event) => {this.openRemoveKeyspaceCellDialog(); }},
@@ -143,6 +145,15 @@ export class KeyspaceComponent implements OnInit, OnDestroy {
143145
this.dialogSettings.toggleModal();
144146
}
145147

148+
openReloadSchemaKeyspaceDialog() {
149+
this.dialogSettings = new DialogSettings('Reload Schema', `Reload Schema in ${this.keyspaceName}`, '',
150+
'There was a problem reloading schema in {{keyspace_name}}:');
151+
this.dialogSettings.setMessage('Reloaded {{keyspace_name}} Schema');
152+
let flags = new ReloadSchemaKeyspaceFlags(this.keyspaceName).flags;
153+
this.dialogContent = new DialogContent('keyspace_name', flags, {}, undefined, 'ReloadSchemaKeyspace');
154+
this.dialogSettings.toggleModal();
155+
}
156+
146157
openRemoveKeyspaceCellDialog() {
147158
this.dialogSettings = new DialogSettings('Remove', `Remove a cell from ${this.keyspaceName}`, '',
148159
'There was a problem removing {{cell_name}}:');

0 commit comments

Comments
 (0)