@@ -93,7 +93,7 @@ func (b *dbMetaMgrBuilder) TableMetaMgr(tr *TableImporter) tableMetaMgr {
93
93
94
94
type tableMetaMgr interface {
95
95
InitTableMeta (ctx context.Context ) error
96
- AllocTableRowIDs (ctx context.Context , rawRowIDMax int64 ) (* verify.KVChecksum , int64 , error )
96
+ AllocTableRowIDs (ctx context.Context , requiredRowIDCnt int64 ) (* verify.KVChecksum , int64 , error )
97
97
UpdateTableStatus (ctx context.Context , status metaStatus ) error
98
98
UpdateTableBaseChecksum (ctx context.Context , checksum * verify.KVChecksum ) error
99
99
CheckAndUpdateLocalChecksum (ctx context.Context , checksum * verify.KVChecksum , hasLocalDupes bool ) (
@@ -177,7 +177,7 @@ func parseMetaStatus(s string) (metaStatus, error) {
177
177
}
178
178
}
179
179
180
- func (m * dbTableMetaMgr ) AllocTableRowIDs (ctx context.Context , rawRowIDMax int64 ) (* verify.KVChecksum , int64 , error ) {
180
+ func (m * dbTableMetaMgr ) AllocTableRowIDs (ctx context.Context , requiredRowIDCnt int64 ) (* verify.KVChecksum , int64 , error ) {
181
181
conn , err := m .session .Conn (ctx )
182
182
if err != nil {
183
183
return nil , 0 , errors .Trace (err )
@@ -188,22 +188,31 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64
188
188
DB : conn ,
189
189
Logger : m .tr .logger ,
190
190
}
191
- var newRowIDBase , newRowIDMax int64
192
- curStatus := metaStatusInitial
191
+ // (myStartRowID, myEndRowID] is the range of row_id that current instance
192
+ // can use to encode the table.
193
+ var myStartRowID , myEndRowID int64
194
+ myStatus := metaStatusInitial
193
195
newStatus := metaStatusRowIDAllocated
194
196
var baseTotalKvs , baseTotalBytes , baseChecksum uint64
195
197
err = exec .Exec (ctx , "enable pessimistic transaction" , "SET SESSION tidb_txn_mode = 'pessimistic';" )
196
198
if err != nil {
197
199
return nil , 0 , errors .Annotate (err , "enable pessimistic transaction failed" )
198
200
}
199
201
200
- needAutoID := common .TableHasAutoID (m .tr .tableInfo .Core )
202
+ hasAutoID := common .TableHasAutoID (m .tr .tableInfo .Core )
201
203
tableChecksumingMsg := "Target table is calculating checksum. Please wait until the checksum is finished and try again."
202
204
doAllocTableRowIDsFn := func () error {
203
205
return exec .Transact (ctx , "init table allocator base" , func (ctx context.Context , tx * sql.Tx ) error {
206
+ // lightning follows below calling sequence, so at most one client
207
+ // can execute the code after the FOR UPDATE part for some table,
208
+ // even though FOR UPDATE only lock rows that matches the condition:
209
+ // - insert into table_meta with key (table_id, task_id)
210
+ // - try lock with FOR UPDATE
204
211
rows , err := tx .QueryContext (
205
212
ctx ,
206
- common .SprintfWithIdentifiers ("SELECT task_id, row_id_base, row_id_max, total_kvs_base, total_bytes_base, checksum_base, status FROM %s.%s WHERE table_id = ? FOR UPDATE" , m .schemaName , m .tableName ),
213
+ common .SprintfWithIdentifiers (`
214
+ SELECT task_id, row_id_base, row_id_max, total_kvs_base, total_bytes_base, checksum_base, status
215
+ FROM %s.%s WHERE table_id = ? FOR UPDATE` , m .schemaName , m .tableName ),
207
216
m .tr .tableInfo .ID ,
208
217
)
209
218
if err != nil {
@@ -234,16 +243,16 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64
234
243
}
235
244
236
245
if metaTaskID == m .taskID {
237
- curStatus = status
246
+ myStatus = status
238
247
baseChecksum = checksum
239
248
baseTotalKvs = totalKvs
240
249
baseTotalBytes = totalBytes
241
250
if status >= metaStatusRowIDAllocated {
242
- if rowIDMax - rowIDBase != rawRowIDMax {
243
- return common .ErrAllocTableRowIDs .GenWithStack ("verify allocator base failed. local: '%d', meta: '%d'" , rawRowIDMax , rowIDMax - rowIDBase )
251
+ if rowIDMax - rowIDBase != requiredRowIDCnt {
252
+ return common .ErrAllocTableRowIDs .GenWithStack ("verify allocator base failed. local: '%d', meta: '%d'" , requiredRowIDCnt , rowIDMax - rowIDBase )
244
253
}
245
- newRowIDBase = rowIDBase
246
- newRowIDMax = rowIDMax
254
+ myStartRowID = rowIDBase
255
+ myEndRowID = rowIDMax
247
256
break
248
257
}
249
258
continue
@@ -263,36 +272,43 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64
263
272
}
264
273
265
274
// no enough info are available, fetch row_id max for table
266
- if curStatus == metaStatusInitial {
267
- if needAutoID {
268
- // maxRowIDMax is the max row_id that other tasks has allocated, we need to rebase the global autoid base first.
269
- // TODO this is not right when AUTO_ID_CACHE=1 and have auto row id,
270
- // the id allocators are separated in this case.
271
- if err := common .RebaseGlobalAutoID (ctx , maxRowIDMax , m .tr , m .tr .dbInfo .ID , m .tr .tableInfo .Core ); err != nil {
272
- return errors .Trace (err )
273
- }
274
- newRowIDBase , newRowIDMax , err = common .AllocGlobalAutoID (ctx , rawRowIDMax , m .tr , m .tr .dbInfo .ID , m .tr .tableInfo .Core )
275
+ if myStatus == metaStatusInitial {
276
+ // if the table don't have auto id, we still guarantee that the
277
+ // row ID is unique across all lightning instances.
278
+ // or if someone have already allocated the auto id, we can continue
279
+ // allocating from previous maxRowIDMax.
280
+ if ! hasAutoID || maxRowIDMax > 0 {
281
+ myStartRowID = maxRowIDMax
282
+ } else {
283
+ // we are the first one to allocate the auto id, we need to
284
+ // fetch the max auto id base from the table, and allocate
285
+ // from there.
286
+ // as we only have one estimated requiredRowIDCount, but the
287
+ // table might have multiple allocators, so we use the max
288
+ // of them.
289
+ maxAutoIDBase , err := common .GetMaxAutoIDBase (m .tr , m .tr .dbInfo .ID , m .tr .tableInfo .Core )
275
290
if err != nil {
276
291
return errors .Trace (err )
277
292
}
278
- } else {
279
- // Though we don't need auto ID, we still guarantee that the row ID is unique across all lightning instances.
280
- newRowIDBase = maxRowIDMax
281
- newRowIDMax = newRowIDBase + rawRowIDMax
293
+ myStartRowID = maxAutoIDBase
282
294
}
295
+ myEndRowID = myStartRowID + requiredRowIDCnt
283
296
284
- // table contains no data, can skip checksum
285
- if needAutoID && newRowIDBase == 0 && newStatus < metaStatusRestoreStarted {
297
+ // if we are the first one to allocate, the table has auto-id,
298
+ // and our start is 0, it means the table is empty, so we move
299
+ // the state to next one directly without going through below
300
+ // checksum branch.
301
+ if hasAutoID && myStartRowID == 0 && newStatus < metaStatusRestoreStarted {
286
302
newStatus = metaStatusRestoreStarted
287
303
}
288
304
289
305
query := common .SprintfWithIdentifiers ("UPDATE %s.%s SET row_id_base = ?, row_id_max = ?, status = ? WHERE table_id = ? AND task_id = ?" , m .schemaName , m .tableName )
290
- _ , err := tx .ExecContext (ctx , query , newRowIDBase , newRowIDMax , newStatus .String (), m .tr .tableInfo .ID , m .taskID )
306
+ _ , err := tx .ExecContext (ctx , query , myStartRowID , myEndRowID , newStatus .String (), m .tr .tableInfo .ID , m .taskID )
291
307
if err != nil {
292
308
return errors .Trace (err )
293
309
}
294
310
295
- curStatus = newStatus
311
+ myStatus = newStatus
296
312
}
297
313
return nil
298
314
})
@@ -325,9 +341,12 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64
325
341
326
342
var checksum * verify.KVChecksum
327
343
// need to do checksum and update checksum meta since we are the first one.
328
- if curStatus < metaStatusRestoreStarted {
329
- // table contains data but haven't do checksum yet
330
- if (newRowIDBase > 0 || ! needAutoID ) && m .needChecksum && baseTotalKvs == 0 {
344
+ if myStatus < metaStatusRestoreStarted {
345
+ // the table might have data if our StartRowID is not 0, or if the table
346
+ // don't have any auto id.
347
+ if (myStartRowID > 0 || ! hasAutoID ) && m .needChecksum && baseTotalKvs == 0 {
348
+ // if another instance finished import before below checksum logic,
349
+ // it will cause checksum mismatch, but it's very rare.
331
350
remoteCk , err := DoChecksum (ctx , m .tr .tableInfo )
332
351
if err != nil {
333
352
return nil , 0 , errors .Trace (err )
@@ -354,11 +373,11 @@ func (m *dbTableMetaMgr) AllocTableRowIDs(ctx context.Context, rawRowIDMax int64
354
373
checksum = & ck
355
374
}
356
375
log .FromContext (ctx ).Info ("allocate table row_id base" , zap .String ("table" , m .tr .tableName ),
357
- zap .Int64 ("row_id_base " , newRowIDBase ))
376
+ zap .Int64 ("startRowID " , myStartRowID ), zap . Int64 ( "endRowID" , myEndRowID ))
358
377
if checksum != nil {
359
378
log .FromContext (ctx ).Info ("checksum base" , zap .Any ("checksum" , checksum ))
360
379
}
361
- return checksum , newRowIDBase , nil
380
+ return checksum , myStartRowID , nil
362
381
}
363
382
364
383
func (m * dbTableMetaMgr ) UpdateTableBaseChecksum (ctx context.Context , checksum * verify.KVChecksum ) error {
0 commit comments