diff --git a/executor/write.go b/executor/write.go index ae010cf3ae048..8da915e995475 100644 --- a/executor/write.go +++ b/executor/write.go @@ -71,20 +71,6 @@ func updateRecord(ctx sessionctx.Context, h int64, oldData, newData []types.Datu return false, handleChanged, newHandle, errors.Trace(err) } } - // Rebase auto increment id if the field is changed. - if mysql.HasAutoIncrementFlag(col.Flag) { - if newData[i].IsNull() { - return false, handleChanged, newHandle, table.ErrColumnCantNull.GenByArgs(col.Name) - } - val, errTI := newData[i].ToInt64(sc) - if errTI != nil { - return false, handleChanged, newHandle, errors.Trace(errTI) - } - err := t.RebaseAutoID(ctx, val, true) - if err != nil { - return false, handleChanged, newHandle, errors.Trace(err) - } - } cmp, err := newData[i].CompareDatum(sc, &oldData[i]) if err != nil { return false, handleChanged, newHandle, errors.Trace(err) @@ -92,6 +78,20 @@ func updateRecord(ctx sessionctx.Context, h int64, oldData, newData []types.Datu if cmp != 0 { changed = true modified[i] = true + // Rebase auto increment id if the field is changed. + if mysql.HasAutoIncrementFlag(col.Flag) { + if newData[i].IsNull() { + return false, handleChanged, newHandle, table.ErrColumnCantNull.GenByArgs(col.Name) + } + val, errTI := newData[i].ToInt64(sc) + if errTI != nil { + return false, handleChanged, newHandle, errors.Trace(errTI) + } + err := t.RebaseAutoID(ctx, val, true) + if err != nil { + return false, handleChanged, newHandle, errors.Trace(err) + } + } if col.IsPKHandleColumn(t.Meta()) { handleChanged = true newHandle = newData[i].GetInt64() diff --git a/executor/write_test.go b/executor/write_test.go index ff2ef8d552ca8..30fa336e9d296 100644 --- a/executor/write_test.go +++ b/executor/write_test.go @@ -2021,3 +2021,36 @@ func (s *testSuite) TestReplaceLog(c *C) { tk.MustQuery(`admin cleanup index testLog b;`).Check(testkit.Rows("1")) } + +// For issue 7422. +// There is no need to do the rebase when updating a record if the auto-increment ID not changed. +// This could make the auto ID increasing speed slower. +func (s *testSuite) TestRebaseIfNeeded(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec(`create table t (a int not null primary key auto_increment, b int unique key);`) + tk.MustExec(`insert into t (b) values (1);`) + + s.ctx = mock.NewContext() + s.ctx.Store = s.store + tbl, err := s.domain.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + c.Assert(err, IsNil) + c.Assert(s.ctx.NewTxn(), IsNil) + // AddRecord directly here will skip to rebase the auto ID in the insert statement, + // which could simulate another TiDB adds a large auto ID. + _, err = tbl.AddRecord(s.ctx, types.MakeDatums(30001, 2), false) + c.Assert(err, IsNil) + c.Assert(s.ctx.Txn().Commit(context.Background()), IsNil) + + tk.MustExec(`update t set b = 3 where a = 30001;`) + tk.MustExec(`insert into t (b) values (4);`) + tk.MustQuery(`select a from t where b = 4;`).Check(testkit.Rows("2")) + + tk.MustExec(`insert into t set b = 3 on duplicate key update a = a;`) + tk.MustExec(`insert into t (b) values (5);`) + tk.MustQuery(`select a from t where b = 5;`).Check(testkit.Rows("4")) + + tk.MustExec(`insert into t set b = 3 on duplicate key update a = a + 1;`) + tk.MustExec(`insert into t (b) values (6);`) + tk.MustQuery(`select a from t where b = 6;`).Check(testkit.Rows("30003")) +}