github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/syncer/sharding-meta/shardmeta_test.go (about)

     1  // Copyright 2019 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package shardmeta
    15  
    16  import (
    17  	"fmt"
    18  	"testing"
    19  
    20  	"github.com/go-mysql-org/go-mysql/mysql"
    21  	"github.com/pingcap/check"
    22  	"github.com/pingcap/tiflow/dm/pkg/binlog"
    23  )
    24  
    25  var _ = check.Suite(&testShardMetaSuite{})
    26  
    27  func TestSuite(t *testing.T) {
    28  	check.TestingT(t)
    29  }
    30  
    31  type testShardMetaSuite struct{}
    32  
    33  func (t *testShardMetaSuite) TestShardingMeta(c *check.C) {
    34  	var (
    35  		active     bool
    36  		err        error
    37  		sqls       []string
    38  		args       [][]interface{}
    39  		location   binlog.Location
    40  		filename   = "mysql-bin.000001"
    41  		table1     = "table1"
    42  		table2     = "table2"
    43  		table3     = "table3"
    44  		metaSchema = "dm_meta"
    45  		metaTable  = "test_syncer_sharding_meta"
    46  		sourceID   = "mysql-replica-01"
    47  		tableID    = "`target_db`.`target_table`"
    48  		meta       = NewShardingMeta(metaSchema, metaTable, false)
    49  		items      = []*DDLItem{
    50  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1000}}, []string{"ddl1"}, table1),
    51  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1200}}, []string{"ddl2-1,ddl2-2"}, table1),
    52  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1400}}, []string{"ddl3"}, table1),
    53  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1600}}, []string{"ddl1"}, table2),
    54  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1800}}, []string{"ddl2-1,ddl2-2"}, table2),
    55  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2000}}, []string{"ddl3"}, table2),
    56  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2200}}, []string{"ddl1"}, table3),
    57  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2400}}, []string{"ddl2-1,ddl2-2"}, table3),
    58  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2600}}, []string{"ddl3"}, table3),
    59  		}
    60  	)
    61  
    62  	// 1st round sharding DDL sync
    63  	for i := 0; i < 7; i++ {
    64  		active, err = meta.AddItem(items[i])
    65  		c.Assert(err, check.IsNil)
    66  		if i%3 == 0 {
    67  			c.Assert(active, check.IsTrue)
    68  		} else {
    69  			c.Assert(active, check.IsFalse)
    70  		}
    71  	}
    72  
    73  	c.Assert(meta.GetGlobalItems(), check.DeepEquals, []*DDLItem{items[0], items[1], items[2]})
    74  	c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[0])
    75  	c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[0])
    76  	c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[3])
    77  	c.Assert(meta.GetActiveDDLItem(table3), check.DeepEquals, items[6])
    78  	c.Assert(meta.InSequenceSharding(), check.IsTrue)
    79  	location, err = meta.ActiveDDLFirstLocation()
    80  	c.Assert(err, check.IsNil)
    81  	c.Assert(location.Position, check.DeepEquals, items[0].FirstLocation.Position)
    82  
    83  	// find synced in shrading group, and call ShardingMeta.ResolveShardingDDL
    84  	c.Assert(meta.ResolveShardingDDL(), check.IsFalse)
    85  
    86  	c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[1])
    87  	c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[1])
    88  	c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[4])
    89  	c.Assert(meta.GetActiveDDLItem(table3), check.IsNil)
    90  	c.Assert(meta.InSequenceSharding(), check.IsTrue)
    91  	location, err = meta.ActiveDDLFirstLocation()
    92  	c.Assert(err, check.IsNil)
    93  	c.Assert(location.Position, check.DeepEquals, items[1].FirstLocation.Position)
    94  
    95  	sqls, args = meta.FlushData(sourceID, tableID)
    96  	c.Assert(sqls, check.HasLen, 4)
    97  	c.Assert(args, check.HasLen, 4)
    98  	for _, stmt := range sqls {
    99  		c.Assert(stmt, check.Matches, "INSERT INTO .*")
   100  	}
   101  	for _, arg := range args {
   102  		c.Assert(arg, check.HasLen, 8)
   103  		c.Assert(arg[3], check.Equals, 1)
   104  	}
   105  
   106  	// 2nd round sharding DDL sync
   107  	for i := 0; i < 8; i++ {
   108  		if i%3 == 0 {
   109  			continue
   110  		}
   111  		active, err = meta.AddItem(items[i])
   112  		c.Assert(err, check.IsNil)
   113  		if i%3 == 1 {
   114  			c.Assert(active, check.IsTrue)
   115  		} else {
   116  			c.Assert(active, check.IsFalse)
   117  		}
   118  	}
   119  
   120  	c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[1])
   121  	c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[1])
   122  	c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[4])
   123  	c.Assert(meta.GetActiveDDLItem(table3), check.DeepEquals, items[7])
   124  	c.Assert(meta.InSequenceSharding(), check.IsTrue)
   125  	location, err = meta.ActiveDDLFirstLocation()
   126  	c.Assert(err, check.IsNil)
   127  	c.Assert(location.Position, check.DeepEquals, items[1].FirstLocation.Position)
   128  
   129  	// find synced in shrading group, and call ShardingMeta.ResolveShardingDDL
   130  	c.Assert(meta.ResolveShardingDDL(), check.IsFalse)
   131  
   132  	c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[2])
   133  	c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[2])
   134  	c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[5])
   135  	c.Assert(meta.GetActiveDDLItem(table3), check.IsNil)
   136  	c.Assert(meta.InSequenceSharding(), check.IsTrue)
   137  	location, err = meta.ActiveDDLFirstLocation()
   138  	c.Assert(err, check.IsNil)
   139  	c.Assert(location.Position, check.DeepEquals, items[2].FirstLocation.Position)
   140  
   141  	sqls, args = meta.FlushData(sourceID, tableID)
   142  	c.Assert(sqls, check.HasLen, 4)
   143  	c.Assert(args, check.HasLen, 4)
   144  	for _, stmt := range sqls {
   145  		c.Assert(stmt, check.Matches, "INSERT INTO .*")
   146  	}
   147  	for _, arg := range args {
   148  		c.Assert(arg, check.HasLen, 8)
   149  		c.Assert(arg[3], check.Equals, 2)
   150  	}
   151  
   152  	// 3rd round sharding DDL sync
   153  	for i := 0; i < 9; i++ {
   154  		if i%3 != 2 {
   155  			continue
   156  		}
   157  		active, err = meta.AddItem(items[i])
   158  		c.Assert(err, check.IsNil)
   159  		if i%3 == 2 {
   160  			c.Assert(active, check.IsTrue)
   161  		} else {
   162  			c.Assert(active, check.IsFalse)
   163  		}
   164  	}
   165  	c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[2])
   166  	c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[2])
   167  	c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[5])
   168  	c.Assert(meta.GetActiveDDLItem(table3), check.DeepEquals, items[8])
   169  	c.Assert(meta.InSequenceSharding(), check.IsTrue)
   170  	location, err = meta.ActiveDDLFirstLocation()
   171  	c.Assert(err, check.IsNil)
   172  	c.Assert(location.Position, check.DeepEquals, items[2].FirstLocation.Position)
   173  
   174  	// find synced in shrading group, and call ShardingMeta.ResolveShardingDDL
   175  	c.Assert(meta.ResolveShardingDDL(), check.IsTrue)
   176  
   177  	c.Assert(meta.GetGlobalActiveDDL(), check.IsNil)
   178  	c.Assert(meta.GetActiveDDLItem(table1), check.IsNil)
   179  	c.Assert(meta.GetActiveDDLItem(table2), check.IsNil)
   180  	c.Assert(meta.GetActiveDDLItem(table3), check.IsNil)
   181  	c.Assert(meta.InSequenceSharding(), check.IsFalse)
   182  	_, err = meta.ActiveDDLFirstLocation()
   183  	c.Assert(err, check.ErrorMatches, fmt.Sprintf("\\[.*\\], Message: activeIdx %d larger than length of global DDLItems: .*", meta.ActiveIdx()))
   184  
   185  	sqls, args = meta.FlushData(sourceID, tableID)
   186  	c.Assert(sqls, check.HasLen, 1)
   187  	c.Assert(args, check.HasLen, 1)
   188  	c.Assert(sqls[0], check.Matches, "DELETE FROM .*")
   189  	c.Assert(args[0], check.DeepEquals, []interface{}{sourceID, tableID})
   190  }
   191  
   192  func (t *testShardMetaSuite) TestShardingMetaWrongSequence(c *check.C) {
   193  	var (
   194  		active   bool
   195  		err      error
   196  		filename = "mysql-bin.000001"
   197  		table1   = "table1"
   198  		table2   = "table2"
   199  		meta     = NewShardingMeta("", "", false)
   200  		items    = []*DDLItem{
   201  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1000}}, []string{"ddl1"}, table1),
   202  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1200}}, []string{"ddl2"}, table1),
   203  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1400}}, []string{"ddl3"}, table1),
   204  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1600}}, []string{"ddl1"}, table2),
   205  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1800}}, []string{"ddl3"}, table2),
   206  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2000}}, []string{"ddl2"}, table2),
   207  		}
   208  	)
   209  
   210  	// 1st round sharding DDL sync
   211  	for i := 0; i < 4; i++ {
   212  		active, err = meta.AddItem(items[i])
   213  		c.Assert(err, check.IsNil)
   214  		if i%3 == 0 {
   215  			c.Assert(active, check.IsTrue)
   216  		} else {
   217  			c.Assert(active, check.IsFalse)
   218  		}
   219  	}
   220  	// find synced in shrading group, and call ShardingMeta.ResolveShardingDDL
   221  	c.Assert(meta.ResolveShardingDDL(), check.IsFalse)
   222  
   223  	// 2nd round sharding DDL sync
   224  	for i := 0; i < 4; i++ {
   225  		if i%3 == 0 {
   226  			continue
   227  		}
   228  		active, err = meta.AddItem(items[i])
   229  		c.Assert(err, check.IsNil)
   230  		if i%3 == 1 {
   231  			c.Assert(active, check.IsTrue)
   232  		} else {
   233  			c.Assert(active, check.IsFalse)
   234  		}
   235  	}
   236  	active, err = meta.AddItem(items[4])
   237  	c.Assert(active, check.IsFalse)
   238  	c.Assert(err, check.ErrorMatches, "\\[.*\\], Message: detect inconsistent DDL sequence from source .*, right DDL sequence should be .*")
   239  }
   240  
   241  func (t *testShardMetaSuite) TestFlushLoadMeta(c *check.C) {
   242  	var (
   243  		active     bool
   244  		err        error
   245  		filename   = "mysql-bin.000001"
   246  		table1     = "table1"
   247  		table2     = "table2"
   248  		metaSchema = "dm_meta"
   249  		metaTable  = "test_syncer_sharding_meta"
   250  		sourceID   = "mysql-replica-01"
   251  		tableID    = "`target_db`.`target_table`"
   252  		meta       = NewShardingMeta(metaSchema, metaTable, false)
   253  		loadedMeta = NewShardingMeta(metaSchema, metaTable, false)
   254  		items      = []*DDLItem{
   255  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1000}}, []string{"ddl1"}, table1),
   256  			NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1200}}, []string{"ddl1"}, table2),
   257  		}
   258  	)
   259  	for _, item := range items {
   260  		active, err = meta.AddItem(item)
   261  		c.Assert(err, check.IsNil)
   262  		c.Assert(active, check.IsTrue)
   263  	}
   264  	sqls, args := meta.FlushData(sourceID, tableID)
   265  	c.Assert(sqls, check.HasLen, 3)
   266  	c.Assert(args, check.HasLen, 3)
   267  	for _, arg := range args {
   268  		c.Assert(arg, check.HasLen, 8)
   269  		c.Assert(loadedMeta.RestoreFromData(arg[2].(string), arg[3].(int), arg[4].(bool), []byte(arg[5].(string)), mysql.MySQLFlavor), check.IsNil)
   270  	}
   271  	c.Assert(loadedMeta.activeIdx, check.Equals, meta.activeIdx)
   272  	c.Assert(loadedMeta.global.String(), check.Equals, meta.global.String())
   273  	c.Assert(loadedMeta.tableName, check.Equals, meta.tableName)
   274  	c.Assert(len(loadedMeta.sources), check.Equals, len(meta.sources))
   275  	for table, source := range loadedMeta.sources {
   276  		c.Assert(source.String(), check.Equals, meta.sources[table].String())
   277  	}
   278  }