vitess.io/vitess@v0.16.2/go/test/endtoend/vreplication/vschema_load_test.go (about) 1 /* 2 Copyright 2022 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 vreplication 18 19 import ( 20 "context" 21 "fmt" 22 "net" 23 "strconv" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/require" 28 29 "vitess.io/vitess/go/test/endtoend/cluster" 30 "vitess.io/vitess/go/vt/log" 31 binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" 32 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 33 vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" 34 "vitess.io/vitess/go/vt/vtgate/vtgateconn" 35 ) 36 37 // TestVSchemaChangesUnderLoad tests vstreamer under a load of high binlog events and simultaneous multiple vschema changes 38 // see https://github.com/vitessio/vitess/issues/11169 39 func TestVSchemaChangesUnderLoad(t *testing.T) { 40 41 extendedTimeout := defaultTimeout * 4 42 43 defaultCellName := "zone1" 44 allCells := []string{"zone1"} 45 allCellNames = "zone1" 46 vc = NewVitessCluster(t, "TestVSchemaChanges", allCells, mainClusterConfig) 47 48 require.NotNil(t, vc) 49 50 defer vc.TearDown(t) 51 52 defaultCell = vc.Cells[defaultCellName] 53 vc.AddKeyspace(t, []*Cell{defaultCell}, "product", "0", initialProductVSchema, initialProductSchema, 1, 0, 100, sourceKsOpts) 54 vtgate = defaultCell.Vtgates[0] 55 require.NotNil(t, vtgate) 56 err := cluster.WaitForHealthyShard(vc.VtctldClient, "product", "0") 57 require.NoError(t, err) 58 vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", "product", "0"), 1, 30*time.Second) 59 vtgateConn = getConnection(t, vc.ClusterConfig.hostname, vc.ClusterConfig.vtgateMySQLPort) 60 defer vtgateConn.Close() 61 62 // ch is used to signal that there is significant data inserted into the tables and when a lot of vschema changes have been applied 63 ch := make(chan bool, 1) 64 65 ctx := context.Background() 66 initialDataInserted := false 67 startCid := 100 68 warmupRowCount := startCid + 2000 69 insertData := func() { 70 timer := time.NewTimer(extendedTimeout) 71 defer timer.Stop() 72 log.Infof("Inserting data into customer") 73 cid := startCid 74 for { 75 if !initialDataInserted && cid > warmupRowCount { 76 log.Infof("Done inserting initial data into customer") 77 initialDataInserted = true 78 ch <- true 79 } 80 query := fmt.Sprintf("insert into customer(cid, name) values (%d, 'a')", cid) 81 _, _ = vtgateConn.ExecuteFetch(query, 1, false) 82 cid++ 83 query = "update customer set name = concat(name, 'a')" 84 _, _ = vtgateConn.ExecuteFetch(query, 10000, false) 85 select { 86 case <-timer.C: 87 log.Infof("Done inserting data into customer") 88 return 89 default: 90 } 91 } 92 } 93 go func() { 94 log.Infof("Starting to vstream from replica") 95 vgtid := &binlogdatapb.VGtid{ 96 ShardGtids: []*binlogdatapb.ShardGtid{{ 97 Keyspace: "product", 98 Shard: "0", 99 Gtid: "", 100 }}} 101 102 filter := &binlogdatapb.Filter{ 103 Rules: []*binlogdatapb.Rule{{ 104 Match: "customer", 105 Filter: "select * from customer", 106 }}, 107 } 108 conn, err := vtgateconn.Dial(ctx, net.JoinHostPort("localhost", strconv.Itoa(vc.ClusterConfig.vtgateGrpcPort))) 109 require.NoError(t, err) 110 defer conn.Close() 111 112 flags := &vtgatepb.VStreamFlags{} 113 114 ctx2, cancel := context.WithTimeout(ctx, extendedTimeout/2) 115 defer cancel() 116 reader, err := conn.VStream(ctx2, topodatapb.TabletType_REPLICA, vgtid, filter, flags) 117 require.NoError(t, err) 118 _, err = reader.Recv() 119 require.NoError(t, err) 120 log.Infof("About to sleep in vstreaming to block the vstream Recv() channel") 121 time.Sleep(extendedTimeout) 122 log.Infof("Done vstreaming") 123 }() 124 125 go insertData() 126 <-ch // wait for enough data to be inserted before ApplyVSchema 127 const maxApplyVSchemas = 20 128 go func() { 129 numApplyVSchema := 0 130 timer := time.NewTimer(extendedTimeout) 131 defer timer.Stop() 132 log.Infof("Started ApplyVSchema") 133 for { 134 if err := vc.VtctlClient.ExecuteCommand("ApplyVSchema", "--", "--vschema={}", "product"); err != nil { 135 log.Errorf("ApplyVSchema command failed with %+v\n", err) 136 return 137 } 138 numApplyVSchema++ 139 if numApplyVSchema > maxApplyVSchemas { 140 ch <- true 141 } 142 select { 143 case <-timer.C: 144 log.Infof("Done ApplyVSchema") 145 ch <- true 146 return 147 default: 148 time.Sleep(defaultTick) 149 } 150 } 151 }() 152 153 <-ch // wait for enough ApplyVSchema calls before doing a PRS 154 if err := vc.VtctlClient.ExecuteCommand("PlannedReparentShard", "--", "--keyspace_shard", "product/0", 155 "--new_primary", "zone1-101", "--wait_replicas_timeout", defaultTimeout.String()); err != nil { 156 require.NoError(t, err, "PlannedReparentShard command failed") 157 } 158 }