vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/vstreamer/uvstreamer_flaky_test.go (about) 1 /* 2 Copyright 2020 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 /* 18 TestVStreamCopyCompleteFlow tests a complete happy VStream Copy flow: copy/catchup/fastforward/replicate 19 Three tables t1, t2, t3 are copied. Initially 10 (numInitialRows) rows are inserted into each. 20 To avoid races in testing we send additional events when *uvstreamerTestMode* is set to true. These are used in 21 conjunction with callbacks to do additional crud at precise points of the flow to test the different paths 22 We intercept the vstreamer send callback to look for specific events and invoke these test callbacks. 23 Fast forward requires tables to be locked briefly to get a snapshot: the test uses this knowledge to hold a lock 24 on the table in order to insert rows for fastforward to find. 25 26 The flow is as follows: 27 t1: copy phase, 10 rows. 28 The lastpk event is intercepted 29 A row is inserted into t1 to be found in catchup 30 A row is inserted into t2 which will be an empty transaction during t1 catchup but will be found in t2 copy 31 t1/t2: catchup phase finds inserted row in t1 32 t2: copy phase to start. Test event is sent, intercepted, we lock t2 to block t2's copy, and a row is inserted into t1 and then unlock 33 t2: fastforward finds t1 event 34 t2: copy starts 35 t2: copy complete 36 t3: copy phase to start. Test event is sent, intercepted, we lock t3 to block t3's copy, and two rows are, one each into t1 and t2 and then unlock 37 t3: fastforward finds t1 and t2 events 38 t3: copy starts 39 t3: copy complete, all tables copied, Copy Complete test event sent, insert 3 rows, one each into t1/t2/t3 40 replicate: finds the 3 inserts, context is cancelled after last expected row callback and its commit, vstream context is cancelled 41 */ 42 43 package vstreamer 44 45 import ( 46 "context" 47 "fmt" 48 "regexp" 49 "strings" 50 "sync" 51 "testing" 52 "time" 53 54 "vitess.io/vitess/go/vt/dbconfigs" 55 56 "vitess.io/vitess/go/sqltypes" 57 "vitess.io/vitess/go/vt/proto/query" 58 59 "github.com/stretchr/testify/require" 60 61 "vitess.io/vitess/go/vt/log" 62 binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" 63 ) 64 65 const ( 66 createTableQuery = "create table %s(id%d1 int, id%d2 int, primary key(id%d1))" 67 bulkInsertQuery = "insert into %s (id%d1, id%d2) values " 68 insertQuery = "insert into %s (id%d1, id%d2) values (%d, %d)" 69 numInitialRows = 10 70 ) 71 72 type state struct { 73 tables []string 74 } 75 76 var testState = &state{} 77 78 var positions map[string]string 79 var allEvents []*binlogdatapb.VEvent 80 var muAllEvents sync.Mutex 81 var callbacks map[string]func() 82 83 func TestVStreamCopyFilterValidations(t *testing.T) { 84 if testing.Short() { 85 t.Skip() 86 } 87 ctx, cancel := context.WithCancel(context.Background()) 88 defer cancel() 89 90 defer execStatements(t, []string{ 91 "drop table t1", 92 "drop table t2a", 93 "drop table t2b", 94 }) 95 96 execStatements(t, []string{ 97 "create table t1(id11 int, id12 int, primary key(id11))", 98 "create table t2a(id21 int, id22 int, primary key(id21))", 99 "create table t2b(id21 int, id22 int, primary key(id21))", 100 }) 101 engine.se.Reload(context.Background()) 102 103 var getUVStreamer = func(filter *binlogdatapb.Filter, tablePKs []*binlogdatapb.TableLastPK) *uvstreamer { 104 uvs := &uvstreamer{ 105 ctx: ctx, 106 cancel: cancel, 107 vse: nil, 108 send: nil, 109 cp: dbconfigs.Connector{}, 110 se: engine.se, 111 startPos: "", 112 filter: filter, 113 vschema: nil, 114 config: nil, 115 inTablePKs: tablePKs, 116 } 117 return uvs 118 } 119 var testFilter = func(rules []*binlogdatapb.Rule, tablePKs []*binlogdatapb.TableLastPK, expected []string, expectedError string) { 120 uvs := getUVStreamer(&binlogdatapb.Filter{Rules: rules}, tablePKs) 121 if expectedError == "" { 122 require.NoError(t, uvs.init()) 123 } else { 124 require.Error(t, uvs.init(), expectedError) 125 return 126 } 127 require.Equal(t, len(expected), len(uvs.plans)) 128 for _, tableName := range expected { 129 require.True(t, uvs.plans[tableName].tablePK.TableName == tableName) 130 if tablePKs == nil { 131 require.Nil(t, uvs.plans[tableName].tablePK.Lastpk) 132 } 133 } 134 for _, pk := range tablePKs { 135 require.Equal(t, uvs.plans[pk.TableName].tablePK, pk) 136 } 137 } 138 139 type TestCase struct { 140 rules []*binlogdatapb.Rule 141 tablePKs []*binlogdatapb.TableLastPK 142 expected []string 143 expectedError string 144 } 145 146 var testCases []*TestCase 147 148 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "t1"}}, nil, []string{"t1"}, ""}) 149 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "t2a"}, {Match: "t1"}}, nil, []string{"t1", "t2a"}, ""}) 150 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "/.*"}}, nil, []string{"t1", "t2a", "t2b"}, ""}) 151 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "/t2.*"}}, nil, []string{"t2a", "t2b"}, ""}) 152 153 tablePKs := []*binlogdatapb.TableLastPK{{ 154 TableName: "t1", 155 Lastpk: getQRFromLastPK([]*query.Field{{Name: "id11", Type: query.Type_INT32}}, []sqltypes.Value{sqltypes.NewInt32(10)}), 156 }} 157 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "t1"}}, tablePKs, []string{"t1"}, ""}) 158 159 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "/.*"}, {Match: "xyz"}}, nil, []string{""}, "table xyz is not present in the database"}) 160 testCases = append(testCases, &TestCase{[]*binlogdatapb.Rule{{Match: "/x.*"}}, nil, []string{""}, "stream needs a position or a table to copy"}) 161 162 for _, tc := range testCases { 163 log.Infof("Running %v", tc.rules) 164 testFilter(tc.rules, tc.tablePKs, tc.expected, tc.expectedError) 165 } 166 } 167 168 func TestVStreamCopyCompleteFlow(t *testing.T) { 169 if testing.Short() { 170 t.Skip() 171 } 172 ctx, cancel := context.WithCancel(context.Background()) 173 defer cancel() 174 engine.se.Reload(context.Background()) 175 176 defer execStatements(t, []string{ 177 "drop table t1", 178 "drop table t2", 179 "drop table t3", 180 }) 181 182 uvstreamerTestMode = true 183 defer func() { uvstreamerTestMode = false }() 184 initialize(t) 185 186 if err := engine.se.Reload(context.Background()); err != nil { 187 t.Fatal("Error reloading schema") 188 } 189 190 var rules []*binlogdatapb.Rule 191 var tablePKs []*binlogdatapb.TableLastPK 192 for i, table := range testState.tables { 193 rules = append(rules, getRule(table)) 194 195 // for table t2, let tablepk be nil, so that we don't send events for the insert in initTables() 196 if table == "t2" { 197 continue 198 } 199 200 tablePKs = append(tablePKs, getTablePK(table, i+1)) 201 } 202 filter := &binlogdatapb.Filter{ 203 Rules: rules, 204 } 205 206 // Test event called after t1 copy is complete 207 callbacks["OTHER.*Copy Start t2"] = func() { 208 conn, err := env.Mysqld.GetDbaConnection(ctx) 209 require.NoError(t, err) 210 defer conn.Close() 211 212 log.Info("Inserting row for fast forward to find, locking t2") 213 conn.ExecuteFetch("lock tables t2 write", 1, false) 214 insertRow(t, "t1", 1, numInitialRows+2) 215 log.Infof("Position after second insert into t1: %s", primaryPosition(t)) 216 conn.ExecuteFetch("unlock tables", 1, false) 217 log.Info("Inserted row for fast forward to find, unlocked tables") 218 219 } 220 221 callbacks["OTHER.*Copy Start t3"] = func() { 222 conn, err := env.Mysqld.GetDbaConnection(ctx) 223 require.NoError(t, err) 224 defer conn.Close() 225 226 log.Info("Inserting row for fast forward to find, locking t3") 227 conn.ExecuteFetch("lock tables t3 write", 1, false) 228 insertRow(t, "t1", 1, numInitialRows+3) 229 insertRow(t, "t2", 2, numInitialRows+2) 230 log.Infof("Position after third insert into t1: %s", primaryPosition(t)) 231 conn.ExecuteFetch("unlock tables", 1, false) 232 log.Info("Inserted rows for fast forward to find, unlocked tables") 233 234 } 235 236 callbacks["COPY_COMPLETED"] = func() { 237 log.Info("Copy done, inserting events to stream") 238 insertRow(t, "t1", 1, numInitialRows+4) 239 insertRow(t, "t2", 2, numInitialRows+3) 240 // savepoints should not be sent in the event stream 241 execStatement(t, ` 242 begin; 243 insert into t3 (id31, id32) values (12, 360); 244 savepoint a; 245 insert into t3 (id31, id32) values (13, 390); 246 rollback work to savepoint a; 247 savepoint b; 248 insert into t3 (id31, id32) values (13, 390); 249 release savepoint b; 250 commit;" 251 `) 252 } 253 254 numCopyEvents := 3 /*t1,t2,t3*/ * (numInitialRows + 1 /*FieldEvent*/ + 1 /*LastPKEvent*/ + 1 /*TestEvent: Copy Start*/ + 2 /*begin,commit*/ + 3 /* LastPK Completed*/) 255 numCopyEvents += 2 /* GTID + Event after all copy is done */ 256 numCatchupEvents := 3 * 5 /* 2 t1, 1 t2 : BEGIN+FIELD+ROW+GTID+COMMIT */ 257 numFastForwardEvents := 5 /*t1:FIELD+ROW*/ 258 numMisc := 1 /* t2 insert during t1 catchup that comes in t2 copy */ 259 numReplicateEvents := 2*5 /* insert into t1/t2 */ + 6 /* begin/field/2 inserts/gtid/commit */ 260 numExpectedEvents := numCopyEvents + numCatchupEvents + numFastForwardEvents + numMisc + numReplicateEvents 261 262 var lastRowEventSeen bool 263 264 callbacks["ROW.*t3.*13390"] = func() { 265 log.Infof("Saw last row event") 266 lastRowEventSeen = true 267 } 268 269 callbacks["COMMIT"] = func() { 270 log.Infof("Got commit, lastRowSeen is %t", lastRowEventSeen) 271 if lastRowEventSeen { 272 log.Infof("Found last row event, canceling context") 273 cancel() 274 } 275 } 276 resetMetrics(t) 277 startVStreamCopy(ctx, t, filter, tablePKs) 278 279 select { 280 case <-time.After(5 * time.Second): 281 printAllEvents("Timed out") 282 t.Fatal("Timed out waiting for events") 283 case <-ctx.Done(): 284 log.Infof("Received context.Done, ending test") 285 } 286 muAllEvents.Lock() 287 defer muAllEvents.Unlock() 288 if len(allEvents) != numExpectedEvents { 289 printAllEvents(fmt.Sprintf("Received %d events, expected %d", len(allEvents), numExpectedEvents)) 290 t.Fatalf("Received %d events, expected %d", len(allEvents), numExpectedEvents) 291 } else { 292 log.Infof("Successfully received %d events", numExpectedEvents) 293 } 294 validateReceivedEvents(t) 295 validateMetrics(t) 296 } 297 298 func validateReceivedEvents(t *testing.T) { 299 for i, ev := range allEvents { 300 ev.Timestamp = 0 301 if ev.Type == binlogdatapb.VEventType_FIELD { 302 for j := range ev.FieldEvent.Fields { 303 ev.FieldEvent.Fields[j].Flags = 0 304 ev.FieldEvent.Keyspace = "" 305 ev.FieldEvent.Shard = "" 306 } 307 } 308 if ev.Type == binlogdatapb.VEventType_ROW { 309 ev.RowEvent.Keyspace = "" 310 ev.RowEvent.Shard = "" 311 } 312 got := ev.String() 313 want := env.RemoveAnyDeprecatedDisplayWidths(expectedEvents[i]) 314 if !strings.HasPrefix(got, want) { 315 printAllEvents("Events not received in the right order") 316 t.Fatalf("Event %d did not match, want %s, got %s", i, want, got) 317 } 318 } 319 } 320 321 func resetMetrics(t *testing.T) { 322 engine.vstreamerEventsStreamed.Reset() 323 engine.resultStreamerNumRows.Reset() 324 engine.rowStreamerNumRows.Reset() 325 engine.vstreamerPhaseTimings.Reset() 326 engine.rowStreamerWaits.Reset() 327 } 328 329 func validateMetrics(t *testing.T) { 330 require.Equal(t, engine.vstreamerEventsStreamed.Get(), int64(len(allEvents))) 331 require.Equal(t, engine.resultStreamerNumRows.Get(), int64(0)) 332 require.Equal(t, engine.rowStreamerNumRows.Get(), int64(31)) 333 require.Equal(t, engine.vstreamerPhaseTimings.Counts()["VStreamerTest.copy"], int64(3)) 334 require.Equal(t, engine.vstreamerPhaseTimings.Counts()["VStreamerTest.catchup"], int64(2)) 335 require.Equal(t, engine.vstreamerPhaseTimings.Counts()["VStreamerTest.fastforward"], int64(2)) 336 require.Equal(t, engine.rowStreamerWaits.Counts()["VStreamerTest.waitForMySQL"], int64(0)) 337 } 338 339 func insertMultipleRows(t *testing.T, table string, idx int, numRows int) { 340 query1 := fmt.Sprintf(bulkInsertQuery, table, idx, idx) 341 s := "" 342 for i := 1; i <= numRows; i++ { 343 if s != "" { 344 s += "," 345 } 346 s += fmt.Sprintf("(%d,%d)", i, i*idx*10) 347 } 348 query1 += s 349 execStatement(t, query1) 350 } 351 352 func initTables(t *testing.T, tables []string) { 353 var idx int 354 positions["start"] = primaryPosition(t) 355 for i, table := range tables { 356 idx = i + 1 357 execStatement(t, fmt.Sprintf(createTableQuery, table, idx, idx, idx)) 358 } 359 for i, table := range tables { 360 tableName := table 361 idx = i + 1 362 insertMultipleRows(t, table, idx, numInitialRows) 363 positions[fmt.Sprintf("%sBulkInsert", table)] = primaryPosition(t) 364 365 callbacks[fmt.Sprintf("LASTPK.*%s.*%d", table, numInitialRows)] = func() { 366 ctx := context.Background() 367 if tableName == "t1" { 368 idx := 1 369 id := numInitialRows + 1 370 table := "t1" 371 query1 := fmt.Sprintf(insertQuery, table, idx, idx, id, id*idx*10) 372 idx = 2 373 table = "t2" 374 query2 := fmt.Sprintf(insertQuery, table, idx, idx, id, id*idx*10) 375 376 queries := []string{ 377 "begin", 378 query1, 379 query2, 380 "commit", 381 } 382 env.Mysqld.ExecuteSuperQueryList(ctx, queries) 383 log.Infof("Position after first insert into t1 and t2: %s", primaryPosition(t)) 384 } 385 } 386 } 387 positions["afterInitialInsert"] = primaryPosition(t) 388 } 389 390 func initialize(t *testing.T) { 391 callbacks = make(map[string]func()) 392 testState.tables = []string{"t1", "t2", "t3"} 393 positions = make(map[string]string) 394 initTables(t, testState.tables) 395 callbacks["gtid.*"+positions["afterInitialInsert"]] = func() { 396 log.Infof("Callback: afterInitialInsert") 397 } 398 } 399 400 func getRule(table string) *binlogdatapb.Rule { 401 return &binlogdatapb.Rule{ 402 Match: table, 403 Filter: fmt.Sprintf("select * from %s", table), 404 } 405 } 406 407 func getTablePK(table string, idx int) *binlogdatapb.TableLastPK { 408 fields := []*query.Field{{Name: fmt.Sprintf("id%d1", idx), Type: query.Type_INT32}} 409 410 lastPK := []sqltypes.Value{sqltypes.NewInt32(0)} 411 return &binlogdatapb.TableLastPK{ 412 TableName: table, 413 Lastpk: getQRFromLastPK(fields, lastPK), 414 } 415 } 416 417 func insertRow(t *testing.T, table string, idx int, id int) { 418 execStatement(t, fmt.Sprintf(insertQuery, table, idx, idx, id, id*idx*10)) 419 } 420 421 func printAllEvents(msg string) { 422 log.Errorf("%s: Received %d events", msg, len(allEvents)) 423 for i, ev := range allEvents { 424 log.Errorf("%d:\t%s", i, ev) 425 } 426 } 427 428 func getEventCallback(event *binlogdatapb.VEvent) func() { 429 s := fmt.Sprintf("%v", event) 430 for key, cb := range callbacks { 431 match := regexp.MustCompile(".*" + key + ".*") 432 if key == s || match.MatchString(s) { 433 return cb 434 } 435 } 436 return nil 437 } 438 439 func startVStreamCopy(ctx context.Context, t *testing.T, filter *binlogdatapb.Filter, tablePKs []*binlogdatapb.TableLastPK) { 440 pos := "" 441 go func() { 442 err := engine.Stream(ctx, pos, tablePKs, filter, func(evs []*binlogdatapb.VEvent) error { 443 //t.Logf("Received events: %v", evs) 444 muAllEvents.Lock() 445 defer muAllEvents.Unlock() 446 for _, ev := range evs { 447 if ev.Type == binlogdatapb.VEventType_HEARTBEAT { 448 continue 449 } 450 if ev.Throttled { 451 continue 452 } 453 cb := getEventCallback(ev) 454 if cb != nil { 455 cb() 456 } 457 allEvents = append(allEvents, ev) 458 } 459 return nil 460 }) 461 require.Nil(t, err) 462 }() 463 } 464 465 var expectedEvents = []string{ 466 "type:OTHER gtid:\"Copy Start t1\"", 467 "type:BEGIN", 468 "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"}}", 469 "type:GTID", 470 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"110\"}}}", 471 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"220\"}}}", 472 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"330\"}}}", 473 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"440\"}}}", 474 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"550\"}}}", 475 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"660\"}}}", 476 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"770\"}}}", 477 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"880\"}}}", 478 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:1 lengths:2 values:\"990\"}}}", 479 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:2 lengths:3 values:\"10100\"}}}", 480 "type:LASTPK last_p_k_event:{table_last_p_k:{table_name:\"t1\" lastpk:{rows:{lengths:2 values:\"10\"}}}}", 481 "type:COMMIT", 482 "type:BEGIN", 483 "type:LASTPK last_p_k_event:{table_last_p_k:{table_name:\"t1\"} completed:true}", 484 "type:COMMIT", 485 "type:BEGIN", 486 "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"}}", 487 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:2 lengths:3 values:\"11110\"}}}", 488 "type:GTID", 489 "type:COMMIT", //insert for t2 done along with t1 does not generate an event since t2 is not yet copied 490 "type:OTHER gtid:\"Copy Start t2\"", 491 "type:BEGIN", 492 "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"}}", 493 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:2 lengths:3 values:\"12120\"}}}", 494 "type:GTID", 495 "type:COMMIT", 496 "type:BEGIN", 497 "type:FIELD field_event:{table_name:\"t2\" fields:{name:\"id21\" type:INT32 table:\"t2\" org_table:\"t2\" database:\"vttest\" org_name:\"id21\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id22\" type:INT32 table:\"t2\" org_table:\"t2\" database:\"vttest\" org_name:\"id22\" column_length:11 charset:63 column_type:\"int(11)\"}}", 498 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:2 values:\"120\"}}}", 499 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:2 values:\"240\"}}}", 500 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:2 values:\"360\"}}}", 501 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:2 values:\"480\"}}}", 502 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:3 values:\"5100\"}}}", 503 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:3 values:\"6120\"}}}", 504 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:3 values:\"7140\"}}}", 505 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:3 values:\"8160\"}}}", 506 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:1 lengths:3 values:\"9180\"}}}", 507 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:2 lengths:3 values:\"10200\"}}}", 508 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:2 lengths:3 values:\"11220\"}}}", 509 "type:LASTPK last_p_k_event:{table_last_p_k:{table_name:\"t2\" lastpk:{rows:{lengths:2 values:\"11\"}}}}", 510 "type:COMMIT", 511 "type:BEGIN", 512 "type:LASTPK last_p_k_event:{table_last_p_k:{table_name:\"t2\"} completed:true}", 513 "type:COMMIT", 514 "type:OTHER gtid:\"Copy Start t3\"", 515 "type:BEGIN", 516 "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"}}", 517 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:2 lengths:3 values:\"13130\"}}}", 518 "type:GTID", 519 "type:COMMIT", 520 "type:BEGIN", 521 "type:FIELD field_event:{table_name:\"t2\" fields:{name:\"id21\" type:INT32 table:\"t2\" org_table:\"t2\" database:\"vttest\" org_name:\"id21\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id22\" type:INT32 table:\"t2\" org_table:\"t2\" database:\"vttest\" org_name:\"id22\" column_length:11 charset:63 column_type:\"int(11)\"}}", 522 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:2 lengths:3 values:\"12240\"}}}", 523 "type:GTID", 524 "type:COMMIT", 525 "type:BEGIN", 526 "type:FIELD field_event:{table_name:\"t3\" fields:{name:\"id31\" type:INT32 table:\"t3\" org_table:\"t3\" database:\"vttest\" org_name:\"id31\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id32\" type:INT32 table:\"t3\" org_table:\"t3\" database:\"vttest\" org_name:\"id32\" column_length:11 charset:63 column_type:\"int(11)\"}}", 527 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:2 values:\"130\"}}}", 528 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:2 values:\"260\"}}}", 529 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:2 values:\"390\"}}}", 530 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:3 values:\"4120\"}}}", 531 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:3 values:\"5150\"}}}", 532 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:3 values:\"6180\"}}}", 533 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:3 values:\"7210\"}}}", 534 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:3 values:\"8240\"}}}", 535 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:1 lengths:3 values:\"9270\"}}}", 536 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:2 lengths:3 values:\"10300\"}}}", 537 "type:LASTPK last_p_k_event:{table_last_p_k:{table_name:\"t3\" lastpk:{rows:{lengths:2 values:\"10\"}}}}", 538 "type:COMMIT", 539 "type:BEGIN", 540 "type:LASTPK last_p_k_event:{table_last_p_k:{table_name:\"t3\"} completed:true}", 541 "type:COMMIT", 542 "type:COPY_COMPLETED", 543 "type:BEGIN", 544 "type:FIELD field_event:{table_name:\"t1\" fields:{name:\"id11\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id11\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id12\" type:INT32 table:\"t1\" org_table:\"t1\" database:\"vttest\" org_name:\"id12\" column_length:11 charset:63 column_type:\"int(11)\"}}", 545 "type:ROW row_event:{table_name:\"t1\" row_changes:{after:{lengths:2 lengths:3 values:\"14140\"}}}", 546 "type:GTID", 547 "type:COMMIT", 548 "type:BEGIN", 549 "type:FIELD field_event:{table_name:\"t2\" fields:{name:\"id21\" type:INT32 table:\"t2\" org_table:\"t2\" database:\"vttest\" org_name:\"id21\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id22\" type:INT32 table:\"t2\" org_table:\"t2\" database:\"vttest\" org_name:\"id22\" column_length:11 charset:63 column_type:\"int(11)\"}}", 550 "type:ROW row_event:{table_name:\"t2\" row_changes:{after:{lengths:2 lengths:3 values:\"13260\"}}}", 551 "type:GTID", 552 "type:COMMIT", 553 "type:BEGIN", 554 "type:FIELD field_event:{table_name:\"t3\" fields:{name:\"id31\" type:INT32 table:\"t3\" org_table:\"t3\" database:\"vttest\" org_name:\"id31\" column_length:11 charset:63 column_type:\"int(11)\"} fields:{name:\"id32\" type:INT32 table:\"t3\" org_table:\"t3\" database:\"vttest\" org_name:\"id32\" column_length:11 charset:63 column_type:\"int(11)\"}}", 555 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:2 lengths:3 values:\"12360\"}}}", 556 "type:ROW row_event:{table_name:\"t3\" row_changes:{after:{lengths:2 lengths:3 values:\"13390\"}}}", 557 "type:GTID", 558 "type:COMMIT", 559 }