From 9cb9b69b61a76e9cc3f8cfa27f86635c2496cf16 Mon Sep 17 00:00:00 2001 From: Yilin Chen Date: Thu, 18 Feb 2021 15:02:32 +0800 Subject: [PATCH] session: ignore linearizability setting for auto-commit transactions (#22746) Signed-off-by: Yilin Chen --- session/session.go | 8 +++++++- session/session_fail_test.go | 17 +++++++++++++++++ store/tikv/2pc.go | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/session/session.go b/session/session.go index 6287c5df35a40..851fd4c2a5ead 100644 --- a/session/session.go +++ b/session/session.go @@ -502,7 +502,13 @@ func (s *session) doCommit(ctx context.Context) error { s.txn.SetOption(kv.Enable1PC, s.GetSessionVars().Enable1PC) // priority of the sysvar is lower than `start transaction with causal consistency only` if s.txn.GetOption(kv.GuaranteeLinearizability) == nil { - s.txn.SetOption(kv.GuaranteeLinearizability, s.GetSessionVars().GuaranteeLinearizability) + // We needn't ask the TiKV client to guarantee linearizability for auto-commit transactions + // because the property is naturally holds: + // We guarantee the commitTS of any transaction must not exceed the next timestamp from the TSO. + // An auto-commit transaction fetches its startTS from the TSO so its commitTS > its startTS > the commitTS + // of any previously committed transactions. + s.txn.SetOption(kv.GuaranteeLinearizability, + !s.GetSessionVars().IsAutocommit() && s.GetSessionVars().GuaranteeLinearizability) } return s.txn.Commit(tikvutil.SetSessionID(ctx, s.GetSessionVars().ConnectionID)) diff --git a/session/session_fail_test.go b/session/session_fail_test.go index 661dabae718a4..193f9bef835e9 100644 --- a/session/session_fail_test.go +++ b/session/session_fail_test.go @@ -103,3 +103,20 @@ func (s *testSessionSerialSuite) TestClusterTableSendError(c *C) { c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1)) c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err, ErrorMatches, ".*TiDB server timeout, address is.*") } + +func (s *testSessionSerialSuite) TestAutoCommitNeedNotLinearizability(c *C) { + tk := testkit.NewTestKitWithInit(c, s.store) + tk.MustExec("drop table if exists t1;") + defer tk.MustExec("drop table if exists t1") + tk.MustExec(`create table t1 (c int)`) + + c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/tikv/getMinCommitTSFromTSO", `panic`), IsNil) + defer failpoint.Disable("github.com/pingcap/tidb/store/tikv/getMinCommitTSFromTSO") + + tk.Se.GetSessionVars().SetSystemVar("tidb_enable_async_commit", "1") + tk.Se.GetSessionVars().SetSystemVar("tidb_guarantee_linearizability", "1") + tk.MustExec("INSERT INTO t1 VALUES (1)") + + tk.Se.GetSessionVars().SetSystemVar("tidb_enable_1pc", "1") + tk.MustExec("INSERT INTO t1 VALUES (2)") +} diff --git a/store/tikv/2pc.go b/store/tikv/2pc.go index a3c63e73cb4f1..9be5ca65250cf 100644 --- a/store/tikv/2pc.go +++ b/store/tikv/2pc.go @@ -1102,6 +1102,7 @@ func (c *twoPhaseCommitter) execute(ctx context.Context) (err error) { // than the snapshot TS of all existent readers. So we get a new timestamp // from PD as our MinCommitTS. if commitTSMayBeCalculated && c.needLinearizability() { + failpoint.Inject("getMinCommitTSFromTSO", nil) minCommitTS, err := c.store.oracle.GetTimestamp(ctx, &oracle.Option{TxnScope: oracle.GlobalTxnScope}) // If we fail to get a timestamp from PD, we just propagate the failure // instead of falling back to the normal 2PC because a normal 2PC will