vitess.io/vitess@v0.16.2/go/vt/vtctl/schematools/reload.go (about) 1 /* 2 Copyright 2021 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package schematools 18 19 import ( 20 "context" 21 "sync" 22 23 "vitess.io/vitess/go/sync2" 24 "vitess.io/vitess/go/vt/logutil" 25 "vitess.io/vitess/go/vt/topo" 26 "vitess.io/vitess/go/vt/topo/topoproto" 27 "vitess.io/vitess/go/vt/vttablet/tmclient" 28 29 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 30 ) 31 32 // ReloadShard reloads the schema for all replica tablets in a shard, after 33 // they reach a given replication position (empty pos means immediate). 34 // 35 // In general, we don't always expect all replicas to be ready to reload, 36 // and the periodic schema reload makes them self-healing anyway. 37 // So we do this on a best-effort basis, and log warnings for any tablets 38 // that fail to reload within the context deadline. 39 func ReloadShard(ctx context.Context, ts *topo.Server, tmc tmclient.TabletManagerClient, logger logutil.Logger, keyspace, shard, replicationPos string, concurrency *sync2.Semaphore, includePrimary bool) (isPartial bool, ok bool) { 40 tablets, err := ts.GetTabletMapForShard(ctx, keyspace, shard) 41 switch { 42 case topo.IsErrType(err, topo.PartialResult): 43 // We got a partial result. Do what we can, but warn 44 // that some may be missed. 45 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) 46 isPartial = true 47 case err == nil: 48 // Good case, keep going too. 49 isPartial = false 50 default: 51 // This is best-effort, so just log it and move on. 52 logger.Warningf("ReloadSchemaShard(%v/%v) failed to load tablet list, will not reload schema (use vtctl ReloadSchemaShard to try again): %v", keyspace, shard, err) 53 return false, false 54 } 55 56 var wg sync.WaitGroup 57 for _, ti := range tablets { 58 if !includePrimary && ti.Type == topodatapb.TabletType_PRIMARY { 59 // We don't need to reload on the primary 60 // because we assume ExecuteFetchAsDba() 61 // already did that. 62 continue 63 } 64 65 wg.Add(1) 66 go func(tablet *topodatapb.Tablet) { 67 defer wg.Done() 68 69 if concurrency != nil { 70 concurrency.Acquire() 71 defer concurrency.Release() 72 } 73 74 pos := replicationPos 75 // Primary is always up-to-date. So, don't wait for position. 76 if tablet.Type == topodatapb.TabletType_PRIMARY { 77 pos = "" 78 } 79 80 if err := tmc.ReloadSchema(ctx, tablet, pos); err != nil { 81 logger.Warningf( 82 "Failed to reload schema on replica tablet %v in %v/%v (use vtctl ReloadSchema to try again): %v", 83 topoproto.TabletAliasString(tablet.Alias), keyspace, shard, err, 84 ) 85 } 86 }(ti.Tablet) 87 } 88 wg.Wait() 89 90 return isPartial, true 91 }