diff --git a/executor/prepared.go b/executor/prepared.go index 95400dd2d2bde..e4090168e4ea1 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -16,16 +16,19 @@ package executor import ( "math" "sort" + "sync/atomic" "fmt" "github.com/pingcap/tidb/ast" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/mysql" "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/plan" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/memory" @@ -345,6 +348,11 @@ func ResetStmtCtx(ctx sessionctx.Context, s ast.StmtNode) (err error) { sc.IgnoreTruncate = true sc.IgnoreZeroInDate = true } + if !sessVars.InRestrictedSQL { + if priority := mysql.PriorityEnum(atomic.LoadInt32(&variable.ForcePriority)); priority != mysql.NoPriority { + sc.Priority = priority + } + } if sessVars.LastInsertID > 0 { sessVars.PrevLastInsertID = sessVars.LastInsertID sessVars.LastInsertID = 0 diff --git a/executor/set_test.go b/executor/set_test.go index 76a7f465e43b0..147bc22d16636 100644 --- a/executor/set_test.go +++ b/executor/set_test.go @@ -221,6 +221,19 @@ func (s *testSuite) TestSetVar(c *C) { tk.MustExec("set @@tidb_general_log = 1") tk.MustExec("set @@tidb_general_log = 0") + + tk.MustExec(`set tidb_force_priority = "no_priority"`) + tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) + tk.MustExec(`set tidb_force_priority = "low_priority"`) + tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("LOW_PRIORITY")) + tk.MustExec(`set tidb_force_priority = "high_priority"`) + tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("HIGH_PRIORITY")) + tk.MustExec(`set tidb_force_priority = "delayed"`) + tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("DELAYED")) + tk.MustExec(`set tidb_force_priority = "abc"`) + tk.MustQuery(`select @@tidb_force_priority;`).Check(testkit.Rows("NO_PRIORITY")) + _, err = tk.Exec(`set global tidb_force_priority = ""`) + c.Assert(err, NotNil) } func (s *testSuite) TestSetCharset(c *C) { diff --git a/mysql/const.go b/mysql/const.go index 78ed47d9b8ef9..e7d632682883e 100644 --- a/mysql/const.go +++ b/mysql/const.go @@ -627,6 +627,31 @@ const ( DelayedPriority ) +// Priority2Str is used to convert the statement priority to string. +var Priority2Str = map[PriorityEnum]string{ + NoPriority: "NO_PRIORITY", + LowPriority: "LOW_PRIORITY", + HighPriority: "HIGH_PRIORITY", + DelayedPriority: "DELAYED", +} + +// Str2Priority is used to convert a string to a priority. +func Str2Priority(val string) PriorityEnum { + val = strings.ToUpper(val) + switch val { + case "NO_PRIORITY": + return NoPriority + case "HIGH_PRIORITY": + return HighPriority + case "LOW_PRIORITY": + return LowPriority + case "DELAYED": + return DelayedPriority + default: + return NoPriority + } +} + // PrimaryKeyName defines primary key name. const ( PrimaryKeyName = "PRIMARY" diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index b7896929d2484..b96723dc817f3 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -576,6 +576,8 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { SetDDLReorgWorkerCounter(int32(tidbOptPositiveInt32(val, DefTiDBDDLReorgWorkerCount))) case TiDBDDLReorgPriority: s.setDDLReorgPriority(val) + case TiDBForcePriority: + atomic.StoreInt32(&ForcePriority, int32(mysql.Str2Priority(val))) } s.systems[name] = val return nil diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 220f901a9c5ce..ebc118b7722b8 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -663,6 +663,7 @@ var defaultSysVars = []*SysVar{ {ScopeSession, TiDBConfig, ""}, {ScopeGlobal | ScopeSession, TiDBDDLReorgWorkerCount, strconv.Itoa(DefTiDBDDLReorgWorkerCount)}, {ScopeSession, TiDBDDLReorgPriority, "PRIORITY_LOW"}, + {ScopeSession, TiDBForcePriority, mysql.Priority2Str[DefTiDBForcePriority]}, } // SynonymsSysVariables is synonyms of system variables. diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index 3c96828778b17..3cb5314d07273 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -15,6 +15,8 @@ package variable import ( "os" + + "github.com/pingcap/tidb/mysql" ) /* @@ -185,6 +187,10 @@ const ( // tidb_ddl_reorg_priority defines the operations priority of adding indices. // It can be: PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH TiDBDDLReorgPriority = "tidb_ddl_reorg_priority" + + // tidb_force_priority defines the operations priority of all statements. + // It can be "NO_PRIORITY", "LOW_PRIORITY", "HIGH_PRIORITY", "DELAYED" + TiDBForcePriority = "tidb_force_priority" ) // Default TiDB system variable values. @@ -224,14 +230,15 @@ const ( DefTiDBDDLReorgWorkerCount = 16 DefTiDBHashAggPartialConcurrency = 4 DefTiDBHashAggFinalConcurrency = 4 + DefTiDBForcePriority = mysql.NoPriority ) // Process global variables. var ( ProcessGeneralLog uint32 - ddlReorgWorkerCounter int32 = DefTiDBDDLReorgWorkerCount - maxDDLReorgWorkerCount int32 = 128 - // DDLSlowOprThreshold is the threshold for ddl slow operations, uint is millisecond. - DDLSlowOprThreshold uint32 = 300 - ServerHostname, _ = os.Hostname() + ddlReorgWorkerCounter int32 = DefTiDBDDLReorgWorkerCount + maxDDLReorgWorkerCount int32 = 128 + DDLSlowOprThreshold uint32 = 300 // DDLSlowOprThreshold is the threshold for ddl slow operations, uint is millisecond. + ForcePriority = int32(DefTiDBForcePriority) + ServerHostname, _ = os.Hostname() ) diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 1ac236c1ad7bb..459b498b7352f 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -83,6 +83,8 @@ func GetSessionOnlySysVars(s *SessionVars, key string) (string, bool, error) { return "", false, errors.Trace(err) } return string(j), true, nil + case TiDBForcePriority: + return mysql.Priority2Str[mysql.PriorityEnum(atomic.LoadInt32(&ForcePriority))], true, nil } sVal, ok := s.systems[key] if ok {