Skip to content

Commit f5e591d

Browse files
authored
*: fix 'Duplicate entry' error when @@auto_increment_increment and @@auto_increment_offset is set (#52626)
close #52622
1 parent a9e3398 commit f5e591d

File tree

5 files changed

+103
-51
lines changed

5 files changed

+103
-51
lines changed

pkg/autoid_service/autoid.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func (alloc *autoIDValue) rebase4Unsigned(ctx context.Context,
200200
return nil
201201
}
202202
// Satisfied by alloc.end, need to update alloc.base.
203-
if requiredBase <= uint64(alloc.end) {
203+
if requiredBase > uint64(alloc.base) && requiredBase <= uint64(alloc.end) {
204204
alloc.base = int64(requiredBase)
205205
return nil
206206
}
@@ -243,7 +243,7 @@ func (alloc *autoIDValue) rebase4Signed(ctx context.Context, store kv.Storage, d
243243
return nil
244244
}
245245
// Satisfied by alloc.end, need to update alloc.base.
246-
if requiredBase <= alloc.end {
246+
if requiredBase > alloc.base && requiredBase <= alloc.end {
247247
alloc.base = requiredBase
248248
return nil
249249
}
@@ -501,6 +501,7 @@ func (s *Service) allocAutoID(ctx context.Context, req *autoid.AutoIDRequest) (*
501501
if err1 != nil {
502502
return err1
503503
}
504+
val.base = currentEnd
504505
val.end = currentEnd
505506
return nil
506507
})

pkg/executor/test/autoidtest/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ go_test(
99
],
1010
flaky = True,
1111
race = "on",
12-
shard_count = 4,
12+
shard_count = 5,
1313
deps = [
1414
"//pkg/autoid_service",
1515
"//pkg/config",

pkg/executor/test/autoidtest/autoid_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,3 +567,43 @@ func TestIssue39528(t *testing.T) {
567567
// Make sure the code does not visit tikv on allocate path.
568568
require.False(t, codeRun)
569569
}
570+
571+
func TestIssue52622(t *testing.T) {
572+
store := testkit.CreateMockStore(t)
573+
574+
tk := testkit.NewTestKit(t, store)
575+
tk.MustExec("use test")
576+
tk.MustExec(`set @@auto_increment_increment = 66;`)
577+
tk.MustExec(`set @@auto_increment_offset = 9527;`)
578+
579+
tk.MustQuery(`select @@auto_increment_increment;`).Check(testkit.Rows("66"))
580+
tk.MustQuery(`select @@auto_increment_offset;`).Check(testkit.Rows("9527"))
581+
582+
for i := 0; i < 2; i++ {
583+
createTableSQL := "create table issue52622 (id int primary key auto_increment, k int)"
584+
if i == 0 {
585+
createTableSQL = createTableSQL + " AUTO_ID_CACHE 1"
586+
}
587+
588+
tk.MustExec(createTableSQL)
589+
tk.MustExec("insert into issue52622 (k) values (1),(2),(3);")
590+
tk.MustQuery("select * from issue52622").Check(testkit.Rows("1 1", "67 2", "133 3"))
591+
if i == 0 {
592+
tk.MustQuery("show create table issue52622").CheckContain("134")
593+
}
594+
tk.MustExec("insert into issue52622 (k) values (4);")
595+
tk.MustQuery("select * from issue52622").Check(testkit.Rows("1 1", "67 2", "133 3", "199 4"))
596+
597+
tk.MustExec("truncate table issue52622;")
598+
tk.MustExec("insert into issue52622 (k) values (1)")
599+
tk.MustExec("insert into issue52622 (k) values (2)")
600+
tk.MustExec("insert into issue52622 (k) values (3)")
601+
if i == 0 {
602+
tk.MustQuery("show create table issue52622").CheckContain("134")
603+
}
604+
tk.MustExec("insert into issue52622 (k) values (4);")
605+
tk.MustQuery("select * from issue52622").Check(testkit.Rows("1 1", "67 2", "133 3", "199 4"))
606+
607+
tk.MustExec("drop table issue52622;")
608+
}
609+
}

pkg/table/table.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/pingcap/tidb/pkg/meta/autoid"
2929
"github.com/pingcap/tidb/pkg/parser/model"
3030
"github.com/pingcap/tidb/pkg/sessionctx"
31+
"github.com/pingcap/tidb/pkg/sessionctx/variable"
3132
tbctx "github.com/pingcap/tidb/pkg/table/context"
3233
"github.com/pingcap/tidb/pkg/types"
3334
"github.com/pingcap/tidb/pkg/util/dbterror"
@@ -214,12 +215,23 @@ type Table interface {
214215
GetPartitionedTable() PartitionedTable
215216
}
216217

218+
func getIncrementAndOffset(vars *variable.SessionVars) (int, int) {
219+
increment := vars.AutoIncrementIncrement
220+
offset := vars.AutoIncrementOffset
221+
// When the value of auto_increment_offset is greater than that of auto_increment_increment,
222+
// the value of auto_increment_offset is ignored.
223+
// Ref https://dev.mysql.com/doc/refman/8.0/en/replication-options-source.html
224+
if offset > increment {
225+
offset = 1
226+
}
227+
return increment, offset
228+
}
229+
217230
// AllocAutoIncrementValue allocates an auto_increment value for a new row.
218231
func AllocAutoIncrementValue(ctx context.Context, t Table, sctx sessionctx.Context) (int64, error) {
219232
r, ctx := tracing.StartRegionEx(ctx, "table.AllocAutoIncrementValue")
220233
defer r.End()
221-
increment := sctx.GetSessionVars().AutoIncrementIncrement
222-
offset := sctx.GetSessionVars().AutoIncrementOffset
234+
increment, offset := getIncrementAndOffset(sctx.GetSessionVars())
223235
alloc := t.Allocators(sctx.GetTableCtx()).Get(autoid.AutoIncrementType)
224236
_, max, err := alloc.Alloc(ctx, uint64(1), int64(increment), int64(offset))
225237
if err != nil {
@@ -230,18 +242,17 @@ func AllocAutoIncrementValue(ctx context.Context, t Table, sctx sessionctx.Conte
230242

231243
// AllocBatchAutoIncrementValue allocates batch auto_increment value for rows, returning firstID, increment and err.
232244
// The caller can derive the autoID by adding increment to firstID for N-1 times.
233-
func AllocBatchAutoIncrementValue(ctx context.Context, t Table, sctx sessionctx.Context, N int) (firstID int64, increment int64, err error) {
234-
increment = int64(sctx.GetSessionVars().AutoIncrementIncrement)
235-
offset := int64(sctx.GetSessionVars().AutoIncrementOffset)
245+
func AllocBatchAutoIncrementValue(ctx context.Context, t Table, sctx sessionctx.Context, N int) ( /* firstID */ int64 /* increment */, int64 /* err */, error) {
246+
increment1, offset := getIncrementAndOffset(sctx.GetSessionVars())
236247
alloc := t.Allocators(sctx.GetTableCtx()).Get(autoid.AutoIncrementType)
237-
min, max, err := alloc.Alloc(ctx, uint64(N), increment, offset)
248+
min, max, err := alloc.Alloc(ctx, uint64(N), int64(increment1), int64(offset))
238249
if err != nil {
239250
return min, max, err
240251
}
241252
// SeekToFirstAutoIDUnSigned seeks to first autoID. Because AutoIncrement always allocate from 1,
242253
// signed and unsigned value can be unified as the unsigned handle.
243-
nr := int64(autoid.SeekToFirstAutoIDUnSigned(uint64(min), uint64(increment), uint64(offset)))
244-
return nr, increment, nil
254+
nr := int64(autoid.SeekToFirstAutoIDUnSigned(uint64(min), uint64(increment1), uint64(offset)))
255+
return nr, int64(increment1), nil
245256
}
246257

247258
// PhysicalTable is an abstraction for two kinds of table representation: partition or non-partitioned table.

tests/integrationtest/r/executor/autoid.result

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -575,123 +575,123 @@ create table io (a int key auto_increment);
575575
insert into io values (null),(null),(null);
576576
select * from io;
577577
a
578-
10
579-
15
580-
20
578+
1
579+
6
580+
11
581581
drop table io;
582582
create table io (a int key auto_increment) AUTO_ID_CACHE 1;
583583
insert into io values (null),(null),(null);
584584
select * from io;
585585
a
586-
10
587-
15
588-
20
586+
1
587+
6
588+
11
589589
drop table io;
590590
create table io (a int key auto_increment);
591591
set auto_increment_offset = 10;
592592
set auto_increment_increment = 2;
593593
insert into io values (),(),();
594594
select * from io;
595595
a
596-
10
597-
12
598-
14
596+
1
597+
3
598+
5
599599
delete from io;
600600
set auto_increment_increment = 5;
601601
insert into io values (),(),();
602602
select * from io;
603603
a
604-
15
605-
20
606-
25
604+
6
605+
11
606+
16
607607
delete from io;
608608
set auto_increment_increment = 10;
609609
insert into io values (),(),();
610610
select * from io;
611611
a
612+
20
612613
30
613614
40
614-
50
615615
delete from io;
616616
set auto_increment_increment = 5;
617617
insert into io values (),(),();
618618
select * from io;
619619
a
620-
55
621-
60
622-
65
620+
41
621+
46
622+
51
623623
drop table io;
624624
create table io (a int key auto_increment) AUTO_ID_CACHE 1;
625625
set auto_increment_offset = 10;
626626
set auto_increment_increment = 2;
627627
insert into io values (),(),();
628628
select * from io;
629629
a
630-
10
631-
12
632-
14
630+
1
631+
3
632+
5
633633
delete from io;
634634
set auto_increment_increment = 5;
635635
insert into io values (),(),();
636636
select * from io;
637637
a
638-
15
639-
20
640-
25
638+
6
639+
11
640+
16
641641
delete from io;
642642
set auto_increment_increment = 10;
643643
insert into io values (),(),();
644644
select * from io;
645645
a
646+
20
646647
30
647648
40
648-
50
649649
delete from io;
650650
set auto_increment_increment = 5;
651651
insert into io values (),(),();
652652
select * from io;
653653
a
654-
55
655-
60
656-
65
654+
41
655+
46
656+
51
657657
drop table io;
658658
set auto_increment_offset = 10;
659659
set auto_increment_increment = 2;
660660
create table io (a int, b int auto_increment, key(b));
661661
insert into io(b) values (null),(null),(null);
662662
select b from io;
663663
b
664-
10
665-
12
666-
14
664+
1
665+
3
666+
5
667667
select _tidb_rowid from io;
668668
_tidb_rowid
669-
15
670-
16
671-
17
669+
6
670+
7
671+
8
672672
delete from io;
673673
set auto_increment_increment = 10;
674674
insert into io(b) values (null),(null),(null);
675675
select b from io;
676676
b
677+
10
677678
20
678679
30
679-
40
680680
select _tidb_rowid from io;
681681
_tidb_rowid
682-
41
683-
42
684-
43
682+
31
683+
32
684+
33
685685
drop table io;
686686
set auto_increment_offset = 10;
687687
set auto_increment_increment = 2;
688688
create table io (a int, b int auto_increment, key(b)) AUTO_ID_CACHE 1;
689689
insert into io(b) values (null),(null),(null);
690690
select b from io;
691691
b
692-
10
693-
12
694-
14
692+
1
693+
3
694+
5
695695
select _tidb_rowid from io;
696696
_tidb_rowid
697697
1
@@ -702,9 +702,9 @@ set auto_increment_increment = 10;
702702
insert into io(b) values (null),(null),(null);
703703
select b from io;
704704
b
705+
10
705706
20
706707
30
707-
40
708708
select _tidb_rowid from io;
709709
_tidb_rowid
710710
4

0 commit comments

Comments
 (0)