github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/restore/meta_manager_test.go (about) 1 // Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0. 2 3 package restore 4 5 import ( 6 "context" 7 "database/sql/driver" 8 9 "github.com/DATA-DOG/go-sqlmock" 10 . "github.com/pingcap/check" 11 "github.com/pingcap/parser" 12 "github.com/pingcap/parser/ast" 13 "github.com/pingcap/parser/model" 14 "github.com/pingcap/tidb/ddl" 15 tmock "github.com/pingcap/tidb/util/mock" 16 "go.uber.org/zap" 17 18 "github.com/pingcap/br/pkg/lightning/checkpoints" 19 "github.com/pingcap/br/pkg/lightning/common" 20 "github.com/pingcap/br/pkg/lightning/log" 21 "github.com/pingcap/br/pkg/lightning/verification" 22 ) 23 24 var _ = Suite(&metaMgrSuite{}) 25 26 type metaMgrSuite struct { 27 mockDB sqlmock.Sqlmock 28 tr *TableRestore 29 mgr *dbTableMetaMgr 30 checksumMgr *testChecksumMgr 31 } 32 33 func (s *metaMgrSuite) SetUpSuite(c *C) { 34 p := parser.New() 35 se := tmock.NewContext() 36 37 node, err := p.ParseOneStmt("CREATE TABLE `t1` (`c1` varchar(5) NOT NULL)", "utf8mb4", "utf8mb4_bin") 38 c.Assert(err, IsNil) 39 tableInfo, err := ddl.MockTableInfo(se, node.(*ast.CreateTableStmt), int64(1)) 40 c.Assert(err, IsNil) 41 tableInfo.State = model.StatePublic 42 43 schema := "test" 44 tb := "t1" 45 ti := &checkpoints.TidbTableInfo{ 46 ID: tableInfo.ID, 47 DB: schema, 48 Name: tb, 49 Core: tableInfo, 50 } 51 52 tableName := common.UniqueTable(schema, tb) 53 logger := log.With(zap.String("table", tableName)) 54 s.tr = &TableRestore{ 55 tableName: tableName, 56 tableInfo: ti, 57 logger: logger, 58 } 59 } 60 61 func (s *metaMgrSuite) SetUpTest(c *C) { 62 db, m, err := sqlmock.New() 63 c.Assert(err, IsNil) 64 65 s.mgr = &dbTableMetaMgr{ 66 session: db, 67 taskID: 1, 68 tr: s.tr, 69 tableName: common.UniqueTable("test", tableMetaTableName), 70 needChecksum: true, 71 } 72 s.mockDB = m 73 s.checksumMgr = &testChecksumMgr{} 74 } 75 76 func (s *metaMgrSuite) TearDownTest(c *C) { 77 c.Assert(s.mockDB.ExpectationsWereMet(), IsNil) 78 } 79 80 func (s *metaMgrSuite) TestAllocTableRowIDsSingleTable(c *C) { 81 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 82 83 rows := [][]driver.Value{ 84 {int64(1), int64(0), int64(0), uint64(0), uint64(0), uint64(0), "initialized"}, 85 } 86 nextID := int64(1) 87 updateArgs := []driver.Value{int64(0), int64(10), "restore", int64(1), int64(1)} 88 s.prepareMock(rows, &nextID, updateArgs, nil, nil) 89 90 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 91 c.Assert(err, IsNil) 92 c.Assert(rowIDBase, Equals, int64(0)) 93 c.Assert(ck, IsNil) 94 c.Assert(s.checksumMgr.callCnt, Equals, 0) 95 } 96 97 func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableAutoIDNot0(c *C) { 98 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 99 100 rows := [][]driver.Value{ 101 {int64(1), int64(0), int64(0), uint64(0), uint64(0), uint64(0), "initialized"}, 102 } 103 nextID := int64(999) 104 updateArgs := []driver.Value{int64(998), int64(1008), "allocated", int64(1), int64(1)} 105 newStatus := "restore" 106 s.prepareMock(rows, &nextID, updateArgs, nil, &newStatus) 107 108 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 109 c.Assert(err, IsNil) 110 c.Assert(rowIDBase, Equals, int64(998)) 111 c.Assert(ck, IsNil) 112 c.Assert(s.checksumMgr.callCnt, Equals, 1) 113 } 114 115 func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableContainsData(c *C) { 116 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 117 118 rows := [][]driver.Value{ 119 {int64(1), int64(0), int64(0), uint64(0), uint64(0), uint64(0), "initialized"}, 120 } 121 nextID := int64(999) 122 checksum := verification.MakeKVChecksum(1, 2, 3) 123 updateArgs := []driver.Value{int64(998), int64(1008), "allocated", int64(1), int64(1)} 124 s.prepareMock(rows, &nextID, updateArgs, &checksum, nil) 125 126 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 127 c.Assert(err, IsNil) 128 c.Assert(rowIDBase, Equals, int64(998)) 129 c.Assert(ck, DeepEquals, &checksum) 130 c.Assert(s.checksumMgr.callCnt, Equals, 1) 131 } 132 133 func (s *metaMgrSuite) TestAllocTableRowIDsSingleTableSkipChecksum(c *C) { 134 s.mgr.needChecksum = false 135 defer func() { 136 s.mgr.needChecksum = true 137 }() 138 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 139 140 rows := [][]driver.Value{ 141 {int64(1), int64(0), int64(0), uint64(0), uint64(0), uint64(0), "initialized"}, 142 } 143 nextID := int64(999) 144 newStatus := "restore" 145 updateArgs := []driver.Value{int64(998), int64(1008), "allocated", int64(1), int64(1)} 146 s.prepareMock(rows, &nextID, updateArgs, nil, &newStatus) 147 148 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 149 c.Assert(err, IsNil) 150 c.Assert(rowIDBase, Equals, int64(998)) 151 c.Assert(ck, IsNil) 152 c.Assert(s.checksumMgr.callCnt, Equals, 0) 153 } 154 155 func (s *metaMgrSuite) TestAllocTableRowIDsAllocated(c *C) { 156 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 157 158 rows := [][]driver.Value{ 159 {int64(1), int64(998), int64(1008), uint64(0), uint64(0), uint64(0), metaStatusRowIDAllocated.String()}, 160 } 161 checksum := verification.MakeKVChecksum(2, 1, 3) 162 s.prepareMock(rows, nil, nil, &checksum, nil) 163 164 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 165 c.Assert(err, IsNil) 166 c.Assert(rowIDBase, Equals, int64(998)) 167 c.Assert(ck, DeepEquals, &checksum) 168 c.Assert(s.checksumMgr.callCnt, Equals, 1) 169 } 170 171 func (s *metaMgrSuite) TestAllocTableRowIDsFinished(c *C) { 172 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 173 174 rows := [][]driver.Value{ 175 {int64(1), int64(998), int64(1008), uint64(1), uint64(2), uint64(3), metaStatusRestoreStarted.String()}, 176 } 177 checksum := verification.MakeKVChecksum(2, 1, 3) 178 s.prepareMock(rows, nil, nil, nil, nil) 179 180 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 181 c.Assert(err, IsNil) 182 c.Assert(rowIDBase, Equals, int64(998)) 183 c.Assert(ck, DeepEquals, &checksum) 184 c.Assert(s.checksumMgr.callCnt, Equals, 0) 185 } 186 187 func (s *metaMgrSuite) TestAllocTableRowIDsMultiTasksInit(c *C) { 188 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 189 190 rows := [][]driver.Value{ 191 {int64(1), int64(0), int64(0), uint64(0), uint64(0), uint64(0), "initialized"}, 192 {int64(2), int64(0), int64(0), uint64(0), uint64(0), uint64(0), "initialized"}, 193 } 194 nextID := int64(1) 195 updateArgs := []driver.Value{int64(0), int64(10), "restore", int64(1), int64(1)} 196 s.prepareMock(rows, &nextID, updateArgs, nil, nil) 197 198 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 199 c.Assert(err, IsNil) 200 c.Assert(rowIDBase, Equals, int64(0)) 201 c.Assert(ck, IsNil) 202 c.Assert(s.checksumMgr.callCnt, Equals, 0) 203 } 204 205 func (s *metaMgrSuite) TestAllocTableRowIDsMultiTasksAllocated(c *C) { 206 ctx := context.WithValue(context.Background(), &checksumManagerKey, s.checksumMgr) 207 208 rows := [][]driver.Value{ 209 {int64(1), int64(0), int64(0), uint64(0), uint64(0), uint64(0), metaStatusInitial.String()}, 210 {int64(2), int64(0), int64(100), uint64(0), uint64(0), uint64(0), metaStatusRowIDAllocated.String()}, 211 } 212 updateArgs := []driver.Value{int64(100), int64(110), "restore", int64(1), int64(1)} 213 s.prepareMock(rows, nil, updateArgs, nil, nil) 214 215 ck, rowIDBase, err := s.mgr.AllocTableRowIDs(ctx, 10) 216 c.Assert(err, IsNil) 217 c.Assert(rowIDBase, Equals, int64(100)) 218 c.Assert(ck, IsNil) 219 c.Assert(s.checksumMgr.callCnt, Equals, 0) 220 } 221 222 func (s *metaMgrSuite) prepareMock(rowsVal [][]driver.Value, nextRowID *int64, updateArgs []driver.Value, checksum *verification.KVChecksum, updateStatus *string) { 223 s.mockDB.ExpectExec("SET SESSION tidb_txn_mode = 'pessimistic';"). 224 WillReturnResult(sqlmock.NewResult(int64(0), int64(0))) 225 226 s.mockDB.ExpectBegin() 227 228 rows := sqlmock.NewRows([]string{"task_id", "row_id_base", "row_id_max", "total_kvs_base", "total_bytes_base", "checksum_base", "status"}) 229 for _, r := range rowsVal { 230 rows = rows.AddRow(r...) 231 } 232 s.mockDB.ExpectQuery("\\QSELECT task_id, row_id_base, row_id_max, total_kvs_base, total_bytes_base, checksum_base, status from `test`.`table_meta` WHERE table_id = ? FOR UPDATE\\E"). 233 WithArgs(int64(1)). 234 WillReturnRows(rows) 235 if nextRowID != nil { 236 s.mockDB.ExpectQuery("SHOW TABLE `test`.`t1` NEXT_ROW_ID"). 237 WillReturnRows(sqlmock.NewRows([]string{"DB_NAME", "TABLE_NAME", "COLUMN_NAME", "NEXT_GLOBAL_ROW_ID", "ID_TYPE"}). 238 AddRow("test", "t1", "_tidb_rowid", *nextRowID, "AUTO_INCREMENT")) 239 } 240 241 if len(updateArgs) > 0 { 242 s.mockDB.ExpectExec("\\Qupdate `test`.`table_meta` set row_id_base = ?, row_id_max = ?, status = ? where table_id = ? and task_id = ?\\E"). 243 WithArgs(updateArgs...). 244 WillReturnResult(sqlmock.NewResult(int64(0), int64(1))) 245 } 246 247 s.mockDB.ExpectCommit() 248 249 if checksum != nil { 250 s.mockDB.ExpectExec("\\Qupdate `test`.`table_meta` set total_kvs_base = ?, total_bytes_base = ?, checksum_base = ?, status = ? where table_id = ? and task_id = ?\\E"). 251 WithArgs(checksum.SumKVS(), checksum.SumSize(), checksum.Sum(), metaStatusRestoreStarted.String(), int64(1), int64(1)). 252 WillReturnResult(sqlmock.NewResult(int64(0), int64(1))) 253 s.checksumMgr.checksum = RemoteChecksum{ 254 TotalBytes: checksum.SumSize(), 255 TotalKVs: checksum.SumKVS(), 256 Checksum: checksum.Sum(), 257 } 258 } 259 260 if updateStatus != nil { 261 s.mockDB.ExpectExec("\\Qupdate `test`.`table_meta` set status = ? where table_id = ? and task_id = ?\\E"). 262 WithArgs(*updateStatus, int64(1), int64(1)). 263 WillReturnResult(sqlmock.NewResult(int64(0), int64(1))) 264 } 265 }