From d48d236d4679c0922ac1132b4a55c3a8e75a4f3b Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Thu, 31 Aug 2023 12:38:09 +0800 Subject: [PATCH] autoid_service: fix potential 'duplicated entry' error when tidb exit for AUTO_ID_CACHE=1 tables #46445 (#46541) close pingcap/tidb#46444 --- autoid_service/autoid.go | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/autoid_service/autoid.go b/autoid_service/autoid.go index 1a4d2b426263e..60e85e411026d 100644 --- a/autoid_service/autoid.go +++ b/autoid_service/autoid.go @@ -187,6 +187,7 @@ func (alloc *autoIDValue) rebase4Unsigned(ctx context.Context, } var newBase, newEnd uint64 + var oldValue int64 startTime := time.Now() ctx = kv.WithInternalSourceType(ctx, kv.InternalTxnMeta) err := kv.RunInNewTxn(ctx, store, true, func(ctx context.Context, txn kv.Transaction) error { @@ -195,6 +196,7 @@ func (alloc *autoIDValue) rebase4Unsigned(ctx context.Context, if err1 != nil { return err1 } + oldValue = currentEnd uCurrentEnd := uint64(currentEnd) newBase = mathutil.Max(uCurrentEnd, requiredBase) newEnd = mathutil.Min(math.MaxUint64-uint64(batch), newBase) + uint64(batch) @@ -205,6 +207,13 @@ func (alloc *autoIDValue) rebase4Unsigned(ctx context.Context, if err != nil { return err } + + logutil.BgLogger().Info("rebase4Unsigned from", + zap.String("category", "autoid service"), + zap.Int64("dbID", dbID), + zap.Int64("tblID", tblID), + zap.Int64("from", oldValue), + zap.Uint64("to", newEnd)) alloc.base, alloc.end = int64(newBase), int64(newEnd) return nil } @@ -220,7 +229,8 @@ func (alloc *autoIDValue) rebase4Signed(ctx context.Context, store kv.Storage, d return nil } - var newBase, newEnd int64 + var oldValue, newBase, newEnd int64 + startTime := time.Now() ctx = kv.WithInternalSourceType(ctx, kv.InternalTxnMeta) err := kv.RunInNewTxn(ctx, store, true, func(ctx context.Context, txn kv.Transaction) error { idAcc := meta.NewMeta(txn).GetAutoIDAccessors(dbID, tblID).IncrementID(model.TableInfoVersion5) @@ -228,14 +238,23 @@ func (alloc *autoIDValue) rebase4Signed(ctx context.Context, store kv.Storage, d if err1 != nil { return err1 } + oldValue = currentEnd newBase = mathutil.Max(currentEnd, requiredBase) newEnd = mathutil.Min(math.MaxInt64-batch, newBase) + batch _, err1 = idAcc.Inc(newEnd - currentEnd) return err1 }) + metrics.AutoIDHistogram.WithLabelValues(metrics.TableAutoIDRebase, metrics.RetLabel(err)).Observe(time.Since(startTime).Seconds()) if err != nil { return err } + + logutil.BgLogger().Info("rebase4Signed from", + zap.Int64("dbID", dbID), + zap.Int64("tblID", tblID), + zap.Int64("from", oldValue), + zap.Int64("to", newEnd), + zap.String("category", "autoid service")) alloc.base, alloc.end = newBase, newEnd return nil } @@ -273,6 +292,11 @@ func New(selfAddr string, etcdAddr []string, store kv.Storage, tlsConfig *tls.Co l := owner.NewOwnerManager(context.Background(), cli, "autoid", selfAddr, autoIDLeaderPath) err = l.CampaignOwner() + l.SetBeOwnerHook(func() { + logutil.BgLogger().Info("leader change of autoid service, this node become owner", + zap.String("addr", selfAddr), + zap.String("category", "autoid service")) + }) if err != nil { panic(err) } @@ -317,7 +341,7 @@ func MockForTest(store kv.Storage) *mockClient { // Close closes the Service and clean up resource. func (s *Service) Close() { - if s.leaderShip != nil { + if s.leaderShip != nil && s.leaderShip.IsOwner() { for k, v := range s.autoIDMap { if v.base > 0 { err := v.forceRebase(context.Background(), s.store, k.dbID, k.tblID, v.base, v.isUnsigned) @@ -465,12 +489,14 @@ func (s *Service) allocAutoID(ctx context.Context, req *autoid.AutoIDRequest) (* func (alloc *autoIDValue) forceRebase(ctx context.Context, store kv.Storage, dbID, tblID, requiredBase int64, isUnsigned bool) error { ctx = kv.WithInternalSourceType(ctx, kv.InternalTxnMeta) + var oldValue int64 err := kv.RunInNewTxn(ctx, store, true, func(ctx context.Context, txn kv.Transaction) error { idAcc := meta.NewMeta(txn).GetAutoIDAccessors(dbID, tblID).IncrementID(model.TableInfoVersion5) currentEnd, err1 := idAcc.Get() if err1 != nil { return err1 } + oldValue = currentEnd var step int64 if !isUnsigned { step = requiredBase - currentEnd @@ -484,6 +510,13 @@ func (alloc *autoIDValue) forceRebase(ctx context.Context, store kv.Storage, dbI if err != nil { return err } + logutil.BgLogger().Info("forceRebase from", + zap.Int64("dbID", dbID), + zap.Int64("tblID", tblID), + zap.Int64("from", oldValue), + zap.Int64("to", requiredBase), + zap.Bool("isUnsigned", isUnsigned), + zap.String("category", "autoid service")) alloc.base, alloc.end = requiredBase, requiredBase return nil }