Skip to content

Commit d8589df

Browse files
authored
*: add a variable to control the back off time and disable txn auto retry by default (#10266)
1 parent 1c4ebee commit d8589df

27 files changed

+109
-58
lines changed

ddl/db_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,7 @@ func (s *testDBSuite8) TestColumn(c *C) {
12801280
s.tk = testkit.NewTestKit(c, s.store)
12811281
s.tk.MustExec("use " + s.schemaName)
12821282
s.tk.MustExec("create table t2 (c1 int, c2 int, c3 int)")
1283+
s.tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
12831284
s.testAddColumn(c)
12841285
s.testDropColumn(c)
12851286
s.tk.MustExec("drop table t2")

executor/set_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,17 @@ func (s *testSuite2) TestSetVar(c *C) {
346346
tk.MustQuery(`select @@session.tidb_wait_table_split_finish;`).Check(testkit.Rows("1"))
347347
tk.MustExec("set tidb_wait_table_split_finish = 0")
348348
tk.MustQuery(`select @@session.tidb_wait_table_split_finish;`).Check(testkit.Rows("0"))
349+
350+
tk.MustExec("set session tidb_back_off_weight = 3")
351+
tk.MustQuery("select @@session.tidb_back_off_weight;").Check(testkit.Rows("3"))
352+
tk.MustExec("set session tidb_back_off_weight = 20")
353+
tk.MustQuery("select @@session.tidb_back_off_weight;").Check(testkit.Rows("20"))
354+
_, err = tk.Exec("set session tidb_back_off_weight = -1")
355+
c.Assert(err, NotNil)
356+
_, err = tk.Exec("set global tidb_back_off_weight = 0")
357+
c.Assert(err, NotNil)
358+
tk.MustExec("set global tidb_back_off_weight = 10")
359+
tk.MustQuery("select @@global.tidb_back_off_weight;").Check(testkit.Rows("10"))
349360
}
350361

351362
func (s *testSuite2) TestSetCharset(c *C) {

executor/write_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,7 @@ func (s *testSuite4) TestAutoIDInRetry(c *C) {
25082508
tk := testkit.NewTestKitWithInit(c, s.store)
25092509
tk.MustExec("create table t (id int not null auto_increment primary key)")
25102510

2511+
tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
25112512
tk.MustExec("begin")
25122513
tk.MustExec("insert into t values ()")
25132514
tk.MustExec("insert into t values (),()")

kv/variables.go

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ type Variables struct {
1818
// BackoffLockFast specifies the LockFast backoff base duration in milliseconds.
1919
BackoffLockFast int
2020

21+
// BackOffWeight specifies the weight of the max back off time duration.
22+
BackOffWeight int
23+
2124
// Hook is used for test to verify the variable take effect.
2225
Hook func(name string, vars *Variables)
2326
}
@@ -26,6 +29,7 @@ type Variables struct {
2629
func NewVariables() *Variables {
2730
return &Variables{
2831
BackoffLockFast: DefBackoffLockFast,
32+
BackOffWeight: DefBackOffWeight,
2933
}
3034
}
3135

@@ -35,4 +39,5 @@ var DefaultVars = NewVariables()
3539
// Default values
3640
const (
3741
DefBackoffLockFast = 100
42+
DefBackOffWeight = 2
3843
)

server/server_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ func runTestConcurrentUpdate(c *C) {
682682
dbt.mustExec("drop table if exists test2")
683683
dbt.mustExec("create table test2 (a int, b int)")
684684
dbt.mustExec("insert test2 values (1, 1)")
685+
dbt.mustExec("set @@tidb_disable_txn_auto_retry = 0")
685686

686687
txn1, err := dbt.db.Begin()
687688
c.Assert(err, IsNil)

session/session.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,8 @@ func (s *session) doCommit(ctx context.Context) error {
356356

357357
// mockCommitError and mockGetTSErrorInRetry use to test PR #8743.
358358
failpoint.Inject("mockCommitError", func(val failpoint.Value) {
359-
if val.(bool) && mockCommitErrorOnce {
360-
mockCommitErrorOnce = false
359+
if val.(bool) && kv.IsMockCommitErrorEnable() {
360+
kv.MockCommitErrorDisable()
361361
failpoint.Return(kv.ErrRetryable)
362362
}
363363
})
@@ -1632,6 +1632,7 @@ var builtinGlobalVariable = []string{
16321632
variable.TiDBHashAggPartialConcurrency,
16331633
variable.TiDBHashAggFinalConcurrency,
16341634
variable.TiDBBackoffLockFast,
1635+
variable.TiDBBackOffWeight,
16351636
variable.TiDBConstraintCheckInPlace,
16361637
variable.TiDBDDLReorgWorkerCount,
16371638
variable.TiDBDDLReorgBatchSize,

session/session_fail_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ func (s *testSessionSuite) TestGetTSFailDirtyState(c *C) {
9595
func (s *testSessionSuite) TestGetTSFailDirtyStateInretry(c *C) {
9696
defer func() {
9797
c.Assert(failpoint.Disable("github.com/pingcap/tidb/session/mockCommitError"), IsNil)
98-
c.Assert(failpoint.Disable("github.com/pingcap/tidb/session/mockGetTSErrorInRetry"), IsNil)
98+
c.Assert(failpoint.Disable("github.com/pingcap/tidb/store/tikv/mockGetTSErrorInRetry"), IsNil)
9999
}()
100100

101101
tk := testkit.NewTestKitWithInit(c, s.store)
102102
tk.MustExec("create table t (id int)")
103103

104104
c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/mockCommitError", `return(true)`), IsNil)
105-
c.Assert(failpoint.Enable("github.com/pingcap/tidb/session/mockGetTSErrorInRetry", `return(true)`), IsNil)
105+
c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/tikv/mockGetTSErrorInRetry", `return(true)`), IsNil)
106106
tk.MustExec("insert into t values (2)")
107107
tk.MustQuery(`select * from t`).Check(testkit.Rows("2"))
108108
}

session/session_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ func (s *testSessionSuite) TestRowLock(c *C) {
293293
tk.MustExec("insert t values (12, 2, 3)")
294294
tk.MustExec("insert t values (13, 2, 3)")
295295

296+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
296297
tk1.MustExec("begin")
297298
tk1.MustExec("update t set c2=21 where c1=11")
298299

@@ -507,6 +508,7 @@ func (s *testSessionSuite) TestRetryResetStmtCtx(c *C) {
507508
tk := testkit.NewTestKitWithInit(c, s.store)
508509
tk.MustExec("create table retrytxn (a int unique, b int)")
509510
tk.MustExec("insert retrytxn values (1, 1)")
511+
tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
510512
tk.MustExec("begin")
511513
tk.MustExec("update retrytxn set b = b + 1 where a = 1")
512514

@@ -665,6 +667,7 @@ func (s *testSessionSuite) TestRetryPreparedStmt(c *C) {
665667
tk.MustExec("create table t (c1 int, c2 int, c3 int)")
666668
tk.MustExec("insert t values (11, 2, 3)")
667669

670+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
668671
tk1.MustExec("begin")
669672
tk1.MustExec("update t set c2=? where c1=11;", 21)
670673

@@ -881,6 +884,7 @@ func (s *testSessionSuite) TestAutoIncrementWithRetry(c *C) {
881884
tk := testkit.NewTestKitWithInit(c, s.store)
882885
tk1 := testkit.NewTestKitWithInit(c, s.store)
883886

887+
tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
884888
tk.MustExec("create table t (c2 int, c1 int not null auto_increment, PRIMARY KEY (c1))")
885889
tk.MustExec("insert into t (c2) values (1), (2), (3), (4), (5)")
886890

@@ -1308,6 +1312,9 @@ func (s *testSessionSuite) TestRetry(c *C) {
13081312
tk2 := testkit.NewTestKitWithInit(c, s.store)
13091313
tk3 := testkit.NewTestKitWithInit(c, s.store)
13101314
tk3.MustExec("SET SESSION autocommit=0;")
1315+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
1316+
tk2.MustExec("set @@tidb_disable_txn_auto_retry = 0")
1317+
tk3.MustExec("set @@tidb_disable_txn_auto_retry = 0")
13111318

13121319
var wg sync.WaitGroup
13131320
wg.Add(3)
@@ -1449,6 +1456,7 @@ func (s *testSessionSuite) TestResetCtx(c *C) {
14491456

14501457
tk.MustExec("create table t (i int auto_increment not null key);")
14511458
tk.MustExec("insert into t values (1);")
1459+
tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
14521460
tk.MustExec("begin;")
14531461
tk.MustExec("insert into t values (10);")
14541462
tk.MustExec("update t set i = i + row_count();")
@@ -1480,6 +1488,8 @@ func (s *testSessionSuite) TestUnique(c *C) {
14801488
tk1 := testkit.NewTestKitWithInit(c, s.store)
14811489
tk2 := testkit.NewTestKitWithInit(c, s.store)
14821490

1491+
tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
1492+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
14831493
tk.MustExec(`CREATE TABLE test ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, val int UNIQUE, PRIMARY KEY (id)); `)
14841494
tk.MustExec("begin;")
14851495
tk.MustExec("insert into test(id, val) values(1, 1);")
@@ -1764,6 +1774,7 @@ func (s *testSchemaSuite) TestSchemaCheckerSQL(c *C) {
17641774
tk.MustExec(`insert into t values(1, 1);`)
17651775

17661776
// The schema version is out of date in the first transaction, but the SQL can be retried.
1777+
tk.MustExec("set @@tidb_disable_txn_auto_retry = 0")
17671778
tk.MustExec(`begin;`)
17681779
tk1.MustExec(`alter table t add index idx(c);`)
17691780
tk.MustExec(`insert into t values(2, 2);`)
@@ -1808,6 +1819,7 @@ func (s *testSchemaSuite) TestPrepareStmtCommitWhenSchemaChanged(c *C) {
18081819
tk1.MustExec("execute stmt using @a, @a")
18091820
tk1.MustExec("commit")
18101821

1822+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
18111823
tk1.MustExec("begin")
18121824
tk.MustExec("alter table t drop column b")
18131825
tk1.MustExec("execute stmt using @a, @a")
@@ -1820,6 +1832,7 @@ func (s *testSchemaSuite) TestCommitWhenSchemaChanged(c *C) {
18201832
tk1 := testkit.NewTestKitWithInit(c, s.store)
18211833
tk.MustExec("create table t (a int, b int)")
18221834

1835+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
18231836
tk1.MustExec("begin")
18241837
tk1.MustExec("insert into t values (1, 1)")
18251838

@@ -1837,6 +1850,7 @@ func (s *testSchemaSuite) TestRetrySchemaChange(c *C) {
18371850
tk.MustExec("create table t (a int primary key, b int)")
18381851
tk.MustExec("insert into t values (1, 1)")
18391852

1853+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
18401854
tk1.MustExec("begin")
18411855
tk1.MustExec("update t set b = 5 where a = 1")
18421856

@@ -1867,6 +1881,7 @@ func (s *testSchemaSuite) TestRetryMissingUnionScan(c *C) {
18671881
tk.MustExec("create table t (a int primary key, b int unique, c int)")
18681882
tk.MustExec("insert into t values (1, 1, 1)")
18691883

1884+
tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0")
18701885
tk1.MustExec("begin")
18711886
tk1.MustExec("update t set b = 1, c = 2 where b = 2")
18721887
tk1.MustExec("update t set b = 1, c = 2 where a = 1")
@@ -2320,9 +2335,12 @@ func (s *testSessionSuite) TestKVVars(c *C) {
23202335
tk.MustExec("insert kvvars values (1, 1)")
23212336
tk2 := testkit.NewTestKitWithInit(c, s.store)
23222337
tk2.MustExec("set @@tidb_backoff_lock_fast = 1")
2338+
tk2.MustExec("set @@tidb_back_off_weight = 100")
23232339
backoffVal := new(int64)
2340+
backOffWeightVal := new(int32)
23242341
tk2.Se.GetSessionVars().KVVars.Hook = func(name string, vars *kv.Variables) {
23252342
atomic.StoreInt64(backoffVal, int64(vars.BackoffLockFast))
2343+
atomic.StoreInt32(backOffWeightVal, int32(vars.BackOffWeight))
23262344
}
23272345
wg := new(sync.WaitGroup)
23282346
wg.Add(2)
@@ -2345,7 +2363,14 @@ func (s *testSessionSuite) TestKVVars(c *C) {
23452363
wg.Done()
23462364
}()
23472365
wg.Wait()
2366+
for {
2367+
tk2.MustQuery("select * from kvvars")
2368+
if atomic.LoadInt32(backOffWeightVal) != 0 {
2369+
break
2370+
}
2371+
}
23482372
c.Assert(atomic.LoadInt64(backoffVal), Equals, int64(1))
2373+
c.Assert(atomic.LoadInt32(backOffWeightVal), Equals, int32(100))
23492374
}
23502375

23512376
func (s *testSessionSuite) TestCommitRetryCount(c *C) {

session/txn.go

-14
Original file line numberDiff line numberDiff line change
@@ -346,25 +346,11 @@ type txnFuture struct {
346346
mockFail bool
347347
}
348348

349-
// mockGetTSErrorInRetryOnce use to make sure gofail mockGetTSErrorInRetry only mock get TS error once.
350-
var mockGetTSErrorInRetryOnce = true
351-
352349
func (tf *txnFuture) wait() (kv.Transaction, error) {
353350
if tf.mockFail {
354351
return nil, errors.New("mock get timestamp fail")
355352
}
356353

357-
// mockGetTSErrorInRetry should wait mockCommitErrorOnce first, then will run into retry() logic.
358-
// Then mockGetTSErrorInRetry will return retryable error when first retry.
359-
// Before PR #8743, we don't cleanup txn after meet error such as error like: PD server timeout[try again later]
360-
// This may cause duplicate data to be written.
361-
failpoint.Inject("mockGetTSErrorInRetry", func(val failpoint.Value) {
362-
if val.(bool) && mockGetTSErrorInRetryOnce && !mockCommitErrorOnce {
363-
mockGetTSErrorInRetryOnce = false
364-
failpoint.Return(nil, errors.Errorf("PD server timeout[try again later]"))
365-
}
366-
})
367-
368354
startTS, err := tf.future.Wait()
369355
if err == nil {
370356
return tf.store.BeginWithStartTS(startTS)

sessionctx/variable/session.go

+2
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,8 @@ func (s *SessionVars) SetSystemVar(name string, val string) error {
699699
s.IndexSerialScanConcurrency = tidbOptPositiveInt32(val, DefIndexSerialScanConcurrency)
700700
case TiDBBackoffLockFast:
701701
s.KVVars.BackoffLockFast = tidbOptPositiveInt32(val, kv.DefBackoffLockFast)
702+
case TiDBBackOffWeight:
703+
s.KVVars.BackOffWeight = tidbOptPositiveInt32(val, kv.DefBackOffWeight)
702704
case TiDBConstraintCheckInPlace:
703705
s.ConstraintCheckInPlace = TiDBOptOn(val)
704706
case TiDBBatchInsert:

sessionctx/variable/sysvar.go

+1
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ var defaultSysVars = []*SysVar{
670670
{ScopeGlobal | ScopeSession, TiDBHashAggPartialConcurrency, strconv.Itoa(DefTiDBHashAggPartialConcurrency)},
671671
{ScopeGlobal | ScopeSession, TiDBHashAggFinalConcurrency, strconv.Itoa(DefTiDBHashAggFinalConcurrency)},
672672
{ScopeGlobal | ScopeSession, TiDBBackoffLockFast, strconv.Itoa(kv.DefBackoffLockFast)},
673+
{ScopeGlobal | ScopeSession, TiDBBackOffWeight, strconv.Itoa(kv.DefBackOffWeight)},
673674
{ScopeGlobal | ScopeSession, TiDBRetryLimit, strconv.Itoa(DefTiDBRetryLimit)},
674675
{ScopeGlobal | ScopeSession, TiDBDisableTxnAutoRetry, BoolToIntStr(DefTiDBDisableTxnAutoRetry)},
675676
{ScopeGlobal | ScopeSession, TiDBConstraintCheckInPlace, BoolToIntStr(DefTiDBConstraintCheckInPlace)},

sessionctx/variable/tidb_vars.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ const (
219219
// tidb_backoff_lock_fast is used for tikv backoff base time in milliseconds.
220220
TiDBBackoffLockFast = "tidb_backoff_lock_fast"
221221

222+
// tidb_back_off_weight is used to control the max back off time in TiDB.
223+
// The default maximum back off time is a small value.
224+
// BackOffWeight could multiply it to let the user adjust the maximum time for retrying.
225+
// Only positive integers can be accepted, which means that the maximum back off time can only grow.
226+
TiDBBackOffWeight = "tidb_back_off_weight"
227+
222228
// tidb_ddl_reorg_worker_cnt defines the count of ddl reorg workers.
223229
TiDBDDLReorgWorkerCount = "tidb_ddl_reorg_worker_cnt"
224230

@@ -300,7 +306,7 @@ const (
300306
DefTiDBMemQuotaDistSQL = 32 << 30 // 32GB.
301307
DefTiDBGeneralLog = 0
302308
DefTiDBRetryLimit = 10
303-
DefTiDBDisableTxnAutoRetry = false
309+
DefTiDBDisableTxnAutoRetry = true
304310
DefTiDBConstraintCheckInPlace = false
305311
DefTiDBHashJoinConcurrency = 5
306312
DefTiDBProjectionConcurrency = 4

sessionctx/variable/varsutil.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ func ValidateSetSystemVar(vars *SessionVars, name string, value string) (string,
388388
TiDBHashAggFinalConcurrency,
389389
TiDBDistSQLScanConcurrency,
390390
TiDBIndexSerialScanConcurrency, TiDBDDLReorgWorkerCount,
391-
TiDBBackoffLockFast,
391+
TiDBBackoffLockFast, TiDBBackOffWeight,
392392
TiDBDMLBatchSize, TiDBOptimizerSelectivityLevel:
393393
v, err := strconv.Atoi(value)
394394
if err != nil {

store/mockstore/mocktikv/mock_tikv_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020

2121
. "github.com/pingcap/check"
2222
"github.com/pingcap/kvproto/pkg/kvrpcpb"
23-
"github.com/pingcap/tidb/util"
2423
)
2524

2625
func TestT(t *testing.T) {
@@ -513,7 +512,7 @@ func (s *testMockTiKVSuite) TestDeleteRange(c *C) {
513512

514513
func (s *testMockTiKVSuite) mustWriteWriteConflict(c *C, errs []error, i int) {
515514
c.Assert(errs[i], NotNil)
516-
c.Assert(strings.Contains(errs[i].Error(), util.WriteConflictMarker), IsTrue)
515+
c.Assert(strings.Contains(errs[i].Error(), writeConflictMarker), IsTrue)
517516
}
518517

519518
func (s *testMockTiKVSuite) TestRC(c *C) {

store/mockstore/mocktikv/mvcc.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/google/btree"
2424
"github.com/pingcap/errors"
2525
"github.com/pingcap/kvproto/pkg/kvrpcpb"
26-
"github.com/pingcap/tidb/util"
2726
"github.com/pingcap/tidb/util/codec"
2827
)
2928

@@ -35,6 +34,8 @@ const (
3534
typeRollback
3635
)
3736

37+
const writeConflictMarker = "write conflict"
38+
3839
type mvccValue struct {
3940
valueType mvccValueType
4041
startTS uint64
@@ -256,7 +257,7 @@ func (e *mvccEntry) Get(ts uint64, isoLevel kvrpcpb.IsolationLevel) ([]byte, err
256257
func (e *mvccEntry) Prewrite(mutation *kvrpcpb.Mutation, startTS uint64, primary []byte, ttl uint64) error {
257258
if len(e.values) > 0 {
258259
if e.values[0].commitTS >= startTS {
259-
return ErrRetryable(util.WriteConflictMarker)
260+
return ErrRetryable(writeConflictMarker)
260261
}
261262
}
262263
if e.lock != nil {

store/mockstore/mocktikv/mvcc_leveldb.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"github.com/pingcap/goleveldb/leveldb/util"
2828
"github.com/pingcap/kvproto/pkg/kvrpcpb"
2929
"github.com/pingcap/parser/terror"
30-
tidbutil "github.com/pingcap/tidb/util"
3130
"github.com/pingcap/tidb/util/codec"
3231
"github.com/pingcap/tidb/util/logutil"
3332
"go.uber.org/zap"
@@ -572,7 +571,7 @@ func prewriteMutation(db *leveldb.DB, batch *leveldb.Batch, mutation *kvrpcpb.Mu
572571
}
573572
// Note that it's a write conflict here, even if the value is a rollback one.
574573
if ok && dec1.value.commitTS >= startTS {
575-
return ErrRetryable(tidbutil.WriteConflictMarker)
574+
return ErrRetryable(writeConflictMarker)
576575
}
577576

578577
op := mutation.GetOp()

store/store_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"time"
2525

2626
. "github.com/pingcap/check"
27-
"github.com/pingcap/errors"
2827
"github.com/pingcap/tidb/kv"
2928
"github.com/pingcap/tidb/store/mockstore"
3029
"github.com/pingcap/tidb/util/logutil"
@@ -40,7 +39,7 @@ const (
4039
type brokenStore struct{}
4140

4241
func (s *brokenStore) Open(schema string) (kv.Storage, error) {
43-
return nil, errors.New("try again later")
42+
return nil, kv.ErrRetryable
4443
}
4544

4645
func TestT(t *testing.T) {
@@ -662,5 +661,5 @@ func (s *testKVSuite) TestRetryOpenStore(c *C) {
662661
}
663662
c.Assert(err, NotNil)
664663
elapse := time.Since(begin)
665-
c.Assert(uint64(elapse), GreaterEqual, uint64(3*time.Second))
664+
c.Assert(uint64(elapse), GreaterEqual, uint64(3*time.Second), Commentf("elapse: %s", elapse))
666665
}

0 commit comments

Comments
 (0)