diff --git a/executor/set_test.go b/executor/set_test.go index d7e28bdd271fe..93af8e0944c7d 100644 --- a/executor/set_test.go +++ b/executor/set_test.go @@ -285,6 +285,49 @@ func (s *testSuite2) TestSetVar(c *C) { c.Assert(err, NotNil) _, err = tk.Exec("set global tidb_batch_commit = 2") c.Assert(err, NotNil) + + // test skip isolation level check: init + tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 0") + tk.MustExec("SET SESSION tidb_skip_isolation_level_check = 0") + tk.MustExec("SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED") + tk.MustExec("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED") + tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) + tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) + tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) + tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) + + // test skip isolation level check: error + _, err = tk.Exec("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE") + c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) + tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) + + _, err = tk.Exec("SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE") + c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedIsolationLevel), IsTrue, Commentf("err %v", err)) + tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("READ-COMMITTED")) + tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("READ-COMMITTED")) + + // test skip isolation level check: success + tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 1") + tk.MustExec("SET SESSION tidb_skip_isolation_level_check = 1") + tk.MustExec("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE") + tk.MustQuery("show warnings").Check(testkit.Rows( + "Warning 1105 The isolation level 'SERIALIZABLE' is not supported. Set tidb_skip_isolation_level_check=1 to skip this error")) + tk.MustQuery("select @@session.tx_isolation").Check(testkit.Rows("SERIALIZABLE")) + tk.MustQuery("select @@session.transaction_isolation").Check(testkit.Rows("SERIALIZABLE")) + + // test skip isolation level check: success + tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 0") + tk.MustExec("SET SESSION tidb_skip_isolation_level_check = 1") + tk.MustExec("SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED") + tk.MustQuery("show warnings").Check(testkit.Rows( + "Warning 1105 The isolation level 'READ-UNCOMMITTED' is not supported. Set tidb_skip_isolation_level_check=1 to skip this error")) + tk.MustQuery("select @@global.tx_isolation").Check(testkit.Rows("READ-UNCOMMITTED")) + tk.MustQuery("select @@global.transaction_isolation").Check(testkit.Rows("READ-UNCOMMITTED")) + + // test skip isolation level check: reset + tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 0") + tk.MustExec("SET SESSION tidb_skip_isolation_level_check = 0") } func (s *testSuite2) TestSetCharset(c *C) { @@ -584,6 +627,8 @@ func (s *testSuite2) TestValidateSetVar(c *C) { result = tk.MustQuery("select @@tx_isolation;") result.Check(testkit.Rows("REPEATABLE-READ")) + tk.MustExec("SET GLOBAL tidb_skip_isolation_level_check = 0") + tk.MustExec("SET SESSION tidb_skip_isolation_level_check = 0") _, err = tk.Exec("set @@tx_isolation='SERIALIZABLE'") c.Assert(terror.ErrorEqual(err, variable.ErrUnsupportedValueForVar), IsTrue, Commentf("err %v", err)) } diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 6209631c79175..220e1adf008bb 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -603,7 +603,21 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { case TxnIsolationOneShot: switch val { case "SERIALIZABLE", "READ-UNCOMMITTED": - return ErrUnsupportedValueForVar.GenWithStackByArgs(name, val) + skipIsolationLevelCheck, err := GetSessionSystemVar(s, TiDBSkipIsolationLevelCheck) + returnErr := ErrUnsupportedIsolationLevel.GenWithStackByArgs(val) + if err != nil { + returnErr = err + } + if !TiDBOptOn(skipIsolationLevelCheck) || err != nil { + return returnErr + } + //SET TRANSACTION ISOLATION LEVEL will affect two internal variables: + // 1. tx_isolation + // 2. transaction_isolation + // The following if condition is used to deduplicate two same warnings. + if name == "transaction_isolation" { + s.StmtCtx.AppendWarning(returnErr) + } } s.TxnIsolationLevelOneShot.State = 1 s.TxnIsolationLevelOneShot.Value = val diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index a4f471054dead..5d705b8cf50e8 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -85,6 +85,7 @@ var ( ErrTruncatedWrongValue = terror.ClassVariable.New(CodeTruncatedWrongValue, mysql.MySQLErrName[mysql.ErrTruncatedWrongValue]) ErrMaxPreparedStmtCountReached = terror.ClassVariable.New(CodeMaxPreparedStmtCountReached, mysql.MySQLErrName[mysql.ErrMaxPreparedStmtCountReached]) ErrUnsupportedValueForVar = terror.ClassVariable.New(CodeUnknownStatusVar, "variable '%s' does not yet support value: %s") + ErrUnsupportedIsolationLevel = terror.ClassVariable.New(CodeUnknownStatusVar, "The isolation level '%s' is not supported. Set tidb_skip_isolation_level_check=1 to skip this error") ) func init() { @@ -673,6 +674,7 @@ var defaultSysVars = []*SysVar{ {ScopeSession, TiDBOptimizerSelectivityLevel, strconv.Itoa(DefTiDBOptimizerSelectivityLevel)}, {ScopeGlobal | ScopeSession, TiDBEnableWindowFunction, BoolToIntStr(DefEnableWindowFunction)}, {ScopeGlobal | ScopeSession, TiDBEnableFastAnalyze, BoolToIntStr(DefTiDBUseFastAnalyze)}, + {ScopeGlobal | ScopeSession, TiDBSkipIsolationLevelCheck, BoolToIntStr(DefTiDBSkipIsolationLevelCheck)}, /* The following variable is defined as session scope but is actually server scope. */ {ScopeSession, TiDBGeneralLog, strconv.Itoa(DefTiDBGeneralLog)}, {ScopeSession, TiDBSlowLogThreshold, strconv.Itoa(logutil.DefaultSlowThreshold)}, diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index a9544c65a0462..5040f66620822 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -131,6 +131,10 @@ const ( // TiDBCheckMb4ValueInUTF8 is used to control whether to enable the check wrong utf8 value. TiDBCheckMb4ValueInUTF8 = "tidb_check_mb4_value_in_utf8" + + // tidb_skip_isolation_level_check is used to control whether to return error when set unsupported transaction + // isolation level. + TiDBSkipIsolationLevelCheck = "tidb_skip_isolation_level_check" ) // TiDB system variable names that both in session and global scope. @@ -295,6 +299,7 @@ const ( DefEnableWindowFunction = false DefTiDBDDLSlowOprThreshold = 300 DefTiDBUseFastAnalyze = false + DefTiDBSkipIsolationLevelCheck = false ) // Process global variables. diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 90cbb54dd6034..c744ed4fd92a0 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -429,7 +429,21 @@ func ValidateSetSystemVar(vars *SessionVars, name string, value string) (string, } switch upVal { case "SERIALIZABLE", "READ-UNCOMMITTED": - return "", ErrUnsupportedValueForVar.GenWithStackByArgs(name, value) + skipIsolationLevelCheck, err := GetSessionSystemVar(vars, TiDBSkipIsolationLevelCheck) + returnErr := ErrUnsupportedIsolationLevel.GenWithStackByArgs(value) + if err != nil { + returnErr = err + } + if !TiDBOptOn(skipIsolationLevelCheck) || err != nil { + return "", returnErr + } + //SET TRANSACTION ISOLATION LEVEL will affect two internal variables: + // 1. tx_isolation + // 2. transaction_isolation + // The following if condition is used to deduplicate two same warnings. + if name == "transaction_isolation" { + vars.StmtCtx.AppendWarning(returnErr) + } } return upVal, nil case TiDBInitChunkSize: