From b8e5460a8426f15a088f58f48a0aa0ce82b342d8 Mon Sep 17 00:00:00 2001 From: BornChanger <97348524+BornChanger@users.noreply.github.com> Date: Thu, 12 Jan 2023 22:01:46 +0800 Subject: [PATCH] *: add new global variable tidb_enable_resource_control as a switch (#40440) ref pingcap/tidb#38825 --- ddl/resource_group_test.go | 18 ++++++++++++++++++ errno/errcode.go | 1 + errno/errname.go | 4 +++- errors.toml | 5 +++++ executor/ddl.go | 9 +++++++++ executor/simple.go | 6 ++++++ executor/simple_test.go | 1 + infoschema/error.go | 2 ++ privilege/privileges/privileges_test.go | 2 ++ session/session.go | 8 +++++++- sessionctx/variable/sysvar.go | 6 ++++++ sessionctx/variable/sysvar_test.go | 25 +++++++++++++++++++++++++ sessionctx/variable/tidb_vars.go | 4 ++++ 13 files changed, 89 insertions(+), 2 deletions(-) diff --git a/ddl/resource_group_test.go b/ddl/resource_group_test.go index 231b3e123ceba..0c2352a4a08c8 100644 --- a/ddl/resource_group_test.go +++ b/ddl/resource_group_test.go @@ -47,6 +47,16 @@ func TestResourceGroupBaisc(t *testing.T) { hook.OnJobUpdatedExported.Store(&onJobUpdatedExportedFunc) dom.DDL().SetHook(hook) + tk.MustExec("set global tidb_enable_resource_control = 'off'") + tk.MustGetErrCode("create user usr1 resource group rg1", mysql.ErrResourceGroupSupportDisabled) + tk.MustExec("create user usr1") + tk.MustGetErrCode("alter user usr1 resource group rg1", mysql.ErrResourceGroupSupportDisabled) + tk.MustGetErrCode("create resource group x "+ + "RRU_PER_SEC=1000 "+ + "WRU_PER_SEC=2000", mysql.ErrResourceGroupSupportDisabled) + + tk.MustExec("set global tidb_enable_resource_control = 'on'") + tk.MustExec("create resource group x " + "RRU_PER_SEC=1000 " + "WRU_PER_SEC=2000") @@ -61,6 +71,14 @@ func TestResourceGroupBaisc(t *testing.T) { g := testResourceGroupNameFromIS(t, tk.Session(), "x") checkFunc(g) + tk.MustExec("set global tidb_enable_resource_control = DEFAULT") + tk.MustGetErrCode("alter resource group x "+ + "RRU_PER_SEC=2000 "+ + "WRU_PER_SEC=3000", mysql.ErrResourceGroupSupportDisabled) + tk.MustGetErrCode("drop resource group x ", mysql.ErrResourceGroupSupportDisabled) + + tk.MustExec("set global tidb_enable_resource_control = 'on'") + tk.MustGetErrCode("create resource group x "+ "RRU_PER_SEC=1000 "+ "WRU_PER_SEC=2000", mysql.ErrResourceGroupExists) diff --git a/errno/errcode.go b/errno/errcode.go index 502d09dd0c562..0d05c6a63f7af 100644 --- a/errno/errcode.go +++ b/errno/errcode.go @@ -1095,6 +1095,7 @@ const ( ErrIngestFailed = 8247 ErrResourceGroupExists = 8248 ErrResourceGroupNotExists = 8249 + ErrResourceGroupSupportDisabled = 8250 // TiKV/PD/TiFlash errors. ErrPDServerTimeout = 9001 diff --git a/errno/errname.go b/errno/errname.go index 01c8e768a873e..1c14f4517e247 100644 --- a/errno/errname.go +++ b/errno/errname.go @@ -1101,7 +1101,9 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{ ErrResourceGroupExists: mysql.Message("Resource group '%-.192s' already exists", nil), ErrResourceGroupNotExists: mysql.Message("Unknown resource group '%-.192s'", nil), - ErrColumnInChange: mysql.Message("column %s id %d does not exist, this column may have been updated by other DDL ran in parallel", nil), + ErrColumnInChange: mysql.Message("column %s id %d does not exist, this column may have been updated by other DDL ran in parallel", nil), + ErrResourceGroupSupportDisabled: mysql.Message("Resource group feature is disabled", nil), + // TiKV/PD errors. ErrPDServerTimeout: mysql.Message("PD server timeout: %s", nil), ErrTiKVServerTimeout: mysql.Message("TiKV server timeout", nil), diff --git a/errors.toml b/errors.toml index 36768c7311e2b..e2708289f132c 100644 --- a/errors.toml +++ b/errors.toml @@ -2531,6 +2531,11 @@ error = ''' Unknown resource group '%-.192s' ''' +["schema:8250"] +error = ''' +Resource group feature is disabled +''' + ["session:8002"] error = ''' [%d] can not retry select for update statement diff --git a/executor/ddl.go b/executor/ddl.go index feca9f5cec523..be8ffa4e48d9f 100644 --- a/executor/ddl.go +++ b/executor/ddl.go @@ -743,13 +743,22 @@ func (e *DDLExec) executeAlterPlacementPolicy(s *ast.AlterPlacementPolicyStmt) e } func (e *DDLExec) executeCreateResourceGroup(s *ast.CreateResourceGroupStmt) error { + if !variable.EnableResourceControl.Load() { + return infoschema.ErrResourceGroupSupportDisabled + } return domain.GetDomain(e.ctx).DDL().CreateResourceGroup(e.ctx, s) } func (e *DDLExec) executeAlterResourceGroup(s *ast.AlterResourceGroupStmt) error { + if !variable.EnableResourceControl.Load() { + return infoschema.ErrResourceGroupSupportDisabled + } return domain.GetDomain(e.ctx).DDL().AlterResourceGroup(e.ctx, s) } func (e *DDLExec) executeDropResourceGroup(s *ast.DropResourceGroupStmt) error { + if !variable.EnableResourceControl.Load() { + return infoschema.ErrResourceGroupSupportDisabled + } return domain.GetDomain(e.ctx).DDL().DropResourceGroup(e.ctx, s) } diff --git a/executor/simple.go b/executor/simple.go index 081ef80c43507..450b03b628fb9 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -1092,6 +1092,9 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm } resourceGroupName := "default" if s.ResourceGroupNameOption != nil { + if !variable.EnableResourceControl.Load() { + return infoschema.ErrResourceGroupSupportDisabled + } if s.ResourceGroupNameOption.Type == ast.UserResourceGroupName { resourceGroupName = s.ResourceGroupNameOption.Value } @@ -1894,6 +1897,9 @@ func (e *SimpleExec) executeAlterUser(ctx context.Context, s *ast.AlterUserStmt) } } if s.ResourceGroupNameOption != nil && s.ResourceGroupNameOption.Type == ast.UserResourceGroupName { + if !variable.EnableResourceControl.Load() { + return infoschema.ErrResourceGroupSupportDisabled + } newAttributes = append(newAttributes, fmt.Sprintf(`"resource_group": "%s"`, s.ResourceGroupNameOption.Value)) } if passwordLockingStr != "" { diff --git a/executor/simple_test.go b/executor/simple_test.go index b5e28a86dcd4b..a188be1ad7d6c 100644 --- a/executor/simple_test.go +++ b/executor/simple_test.go @@ -128,6 +128,7 @@ func TestUserAttributes(t *testing.T) { rootTK.MustExec("create user usr1@'%' identified by 'passord'") rootTK.MustExec("alter user usr1 comment 'comment1'") rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}, "resource_group": "default"}`)) + rootTK.MustExec("set global tidb_enable_resource_control = 'on'") rootTK.MustExec("alter user usr1 resource group rg1") rootTK.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}, "resource_group": "rg1"}`)) } diff --git a/infoschema/error.go b/infoschema/error.go index a2bbc41fb3505..2e1a45c7ae113 100644 --- a/infoschema/error.go +++ b/infoschema/error.go @@ -100,4 +100,6 @@ var ( ErrForeignKeyNoIndexInParent = dbterror.ClassSchema.NewStd(mysql.ErrForeignKeyNoIndexInParent) // ErrForeignKeyColumnNotNull returns when foreign key with SET NULL constrain and the related column has not null. ErrForeignKeyColumnNotNull = dbterror.ClassSchema.NewStd(mysql.ErrForeignKeyColumnNotNull) + // ErrResourceGroupSupportDisabled returns for resource group feature is disabled + ErrResourceGroupSupportDisabled = dbterror.ClassSchema.NewStd(mysql.ErrResourceGroupSupportDisabled) ) diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 1e4f0cafca5ed..18de50ae11036 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -515,6 +515,7 @@ func TestAlterUserStmt(t *testing.T) { tk.MustExec("GRANT RESTRICTED_USER_ADMIN ON *.* TO semuser1, semuser2, semuser3") tk.MustExec("GRANT SYSTEM_USER ON *.* to semuser3") // user is both restricted + has SYSTEM_USER (or super) + tk.MustExec("set global tidb_enable_resource_control = 'on'") tk.MustExec(`ALTER USER 'semuser1' RESOURCE GROUP rg1`) tk.MustQuery(`SELECT User_attributes FROM mysql.user WHERE User = "semuser1"`).Check(testkit.Rows("{\"resource_group\": \"rg1\"}")) @@ -1135,6 +1136,7 @@ func TestCreateDropUser(t *testing.T) { tk.MustQuery(`SELECT User_attributes FROM mysql.user WHERE User = "usr1"`).Check(testkit.Rows("{\"resource_group\": \"default\"}")) tk.MustExec(`DROP USER usr1`) + tk.MustExec("set global tidb_enable_resource_control = 'on'") tk.MustExec(`CREATE USER usr1 RESOURCE GROUP rg1`) tk.MustQuery(`SELECT User_attributes FROM mysql.user WHERE User = "usr1"`).Check(testkit.Rows("{\"resource_group\": \"rg1\"}")) tk.MustExec(`DROP USER usr1`) diff --git a/session/session.go b/session/session.go index f6dbed8dbadc2..6296e1556b937 100644 --- a/session/session.go +++ b/session/session.go @@ -2678,7 +2678,13 @@ func (s *session) Auth(user *auth.UserIdentity, authentication, salt []byte) err } return err } - s.sessionVars.ResourceGroupName = info.ResourceGroupName + + // If tidb_resource_control_enable is disabled, set resource group to empty + if variable.EnableResourceControl.Load() { + s.sessionVars.ResourceGroupName = strings.ToLower(info.ResourceGroupName) + } else { + s.sessionVars.ResourceGroupName = "" + } if info.InSandBoxMode { // Enter sandbox mode, only execute statement for resetting password. s.EnableSandBoxMode() diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 726043595651d..f634abac1cc98 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -2248,6 +2248,12 @@ var defaultSysVars = []*SysVar{ return strconv.Itoa(int(TTLDeleteWorkerCount.Load())), nil }, }, + {Scope: ScopeGlobal, Name: TiDBEnableResourceControl, Value: BoolToOnOff(DefTiDBEnableResourceControl), Type: TypeBool, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { + EnableResourceControl.Store(TiDBOptOn(s)) + return nil + }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { + return BoolToOnOff(EnableResourceControl.Load()), nil + }}, } // FeedbackProbability points to the FeedbackProbability in statistics package. diff --git a/sessionctx/variable/sysvar_test.go b/sessionctx/variable/sysvar_test.go index 77d54e502b780..91ebc8ec996a0 100644 --- a/sessionctx/variable/sysvar_test.go +++ b/sessionctx/variable/sysvar_test.go @@ -1113,3 +1113,28 @@ func TestSetJobScheduleWindow(t *testing.T) { require.NoError(t, err) require.Equal(t, "16:11 +0800", val) } + +func TestTiDBEnableResourceControl(t *testing.T) { + vars := NewSessionVars(nil) + mock := NewMockGlobalAccessor4Tests() + mock.SessionVars = vars + vars.GlobalVarsAccessor = mock + resourceControlEnabled := GetSysVar(TiDBEnableResourceControl) + + // Default true + require.Equal(t, resourceControlEnabled.Value, Off) + + // Set to On + err := mock.SetGlobalSysVar(context.Background(), TiDBEnableResourceControl, On) + require.NoError(t, err) + val, err1 := mock.GetGlobalSysVar(TiDBEnableResourceControl) + require.NoError(t, err1) + require.Equal(t, On, val) + + // Set to off + err = mock.SetGlobalSysVar(context.Background(), TiDBEnableResourceControl, Off) + require.NoError(t, err) + val, err1 = mock.GetGlobalSysVar(TiDBEnableResourceControl) + require.NoError(t, err1) + require.Equal(t, Off, val) +} diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index 04bb8739813ae..086f8c224501c 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -894,6 +894,8 @@ const ( TiDBHistoricalStatsDuration = "tidb_historical_stats_duration" // TiDBEnableHistoricalStatsForCapture indicates whether use historical stats in plan replayer capture TiDBEnableHistoricalStatsForCapture = "tidb_enable_historical_stats_for_capture" + // TiDBEnableResourceControl indicates whether resource control feature is enabled + TiDBEnableResourceControl = "tidb_enable_resource_control" ) // TiDB intentional limits @@ -1153,6 +1155,7 @@ const ( DefTiDBTTLJobScheduleWindowEndTime = "23:59 +0000" DefTiDBTTLScanWorkerCount = 4 DefTiDBTTLDeleteWorkerCount = 4 + DefTiDBEnableResourceControl = false ) // Process global variables. @@ -1229,6 +1232,7 @@ var ( MaxPreparedStmtCountValue = atomic.NewInt64(DefMaxPreparedStmtCount) HistoricalStatsDuration = atomic.NewDuration(DefTiDBHistoricalStatsDuration) EnableHistoricalStatsForCapture = atomic.NewBool(DefTiDBEnableHistoricalStatsForCapture) + EnableResourceControl = atomic.NewBool(DefTiDBEnableResourceControl) ) var (