diff --git a/ddl/resource_group_test.go b/ddl/resource_group_test.go index 2a396488483d..a0921037c475 100644 --- a/ddl/resource_group_test.go +++ b/ddl/resource_group_test.go @@ -16,7 +16,6 @@ package ddl_test import ( "context" - "strconv" "testing" "github.com/pingcap/tidb/ddl/internal/callback" @@ -89,16 +88,17 @@ func TestResourceGroupBasic(t *testing.T) { re.Equal(uint64(2000), g.RURate) re.Equal(int64(-1), g.BurstLimit) - tk.MustExec("alter resource group if exists not_exists RU_PER_SEC=2000") - // Check warning message - res = tk.MustQuery("show warnings") - res.Check(testkit.Rows("Note 8249 Unknown resource group 'not_exists'")) + tk.MustQuery("select * from information_schema.resource_groups where name = 'x'").Check(testkit.Rows("x 2000 0 YES")) - tk.MustQuery("select * from information_schema.resource_groups where group_name = 'x' ").Check(testkit.Rows(strconv.FormatInt(g.ID, 10) + " x 2000")) tk.MustExec("drop resource group x") g = testResourceGroupNameFromIS(t, tk.Session(), "x") re.Nil(g) + tk.MustExec("alter resource group if exists not_exists RU_PER_SEC=2000") + // Check warning message + res = tk.MustQuery("show warnings") + res.Check(testkit.Rows("Note 8249 Unknown resource group 'not_exists'")) + tk.MustExec("create resource group y " + "CPU='4000m' " + "IO_READ_BANDWIDTH='1G' " + @@ -137,29 +137,38 @@ func TestResourceGroupBasic(t *testing.T) { // Check information schema table information_schema.resource_groups tk.MustExec("create resource group x RU_PER_SEC=1000") - g1 := testResourceGroupNameFromIS(t, tk.Session(), "x") - tk.MustQuery("select * from information_schema.resource_groups where group_name = 'x'").Check(testkit.Rows(strconv.FormatInt(g1.ID, 10) + " x 1000")) + tk.MustQuery("select * from information_schema.resource_groups where name = 'x'").Check(testkit.Rows("x 1000 0 NO")) tk.MustQuery("show create resource group x").Check(testkit.Rows("x CREATE RESOURCE GROUP `x` RU_PER_SEC=1000")) tk.MustExec("create resource group y RU_PER_SEC=2000") - g2 := testResourceGroupNameFromIS(t, tk.Session(), "y") - tk.MustQuery("select * from information_schema.resource_groups where group_name = 'y'").Check(testkit.Rows(strconv.FormatInt(g2.ID, 10) + " y 2000")) + tk.MustQuery("select * from information_schema.resource_groups where name = 'y'").Check(testkit.Rows("y 2000 0 NO")) tk.MustQuery("show create resource group y").Check(testkit.Rows("y CREATE RESOURCE GROUP `y` RU_PER_SEC=2000")) - tk.MustExec("alter resource group y RU_PER_SEC=4000") - - g2 = testResourceGroupNameFromIS(t, tk.Session(), "y") - tk.MustQuery("select * from information_schema.resource_groups where group_name = 'y'").Check(testkit.Rows(strconv.FormatInt(g2.ID, 10) + " y 4000")) - tk.MustQuery("show create resource group y").Check(testkit.Rows("y CREATE RESOURCE GROUP `y` RU_PER_SEC=4000")) + tk.MustExec("alter resource group y RU_PER_SEC=4000 BURSTABLE") + tk.MustQuery("select * from information_schema.resource_groups where name = 'y'").Check(testkit.Rows("y 4000 0 YES")) + tk.MustQuery("show create resource group y").Check(testkit.Rows("y CREATE RESOURCE GROUP `y` RU_PER_SEC=4000 BURSTABLE")) tk.MustQuery("select count(*) from information_schema.resource_groups").Check(testkit.Rows("2")) tk.MustGetErrCode("create user usr_fail resource group nil_group", mysql.ErrResourceGroupNotExists) + tk.MustContainErrMsg("create user usr_fail resource group nil_group", "Unknown resource group 'nil_group'") tk.MustExec("create user user2") tk.MustGetErrCode("alter user user2 resource group nil_group", mysql.ErrResourceGroupNotExists) + tk.MustContainErrMsg("alter user user2 resource group nil_group", "Unknown resource group 'nil_group'") + + tk.MustExec("create resource group z " + + "CPU='4000m' " + + "IO_READ_BANDWIDTH='1G' " + + "IO_WRITE_BANDWIDTH='300M'") + tk.MustQuery("show create resource group z").Check(testkit.Rows("z CREATE RESOURCE GROUP `z` CPU=\"4000m\" IO_READ_BANDWIDTH=\"1G\" IO_WRITE_BANDWIDTH=\"300M\"")) tk.MustExec("create resource group do_not_delete_rg ru_per_sec=100") tk.MustExec("create user usr3 resource group do_not_delete_rg") + tk.MustQuery("select user_attributes from mysql.user where user = 'usr3'").Check(testkit.Rows(`{"resource_group": "do_not_delete_rg"}`)) tk.MustContainErrMsg("drop resource group do_not_delete_rg", "user [usr3] depends on the resource group to drop") + tk.MustExec("alter user usr3 resource group `default`") + tk.MustExec("alter user usr3 resource group ``") + tk.MustExec("alter user usr3 resource group `DeFault`") + tk.MustQuery("select user_attributes from mysql.user where user = 'usr3'").Check(testkit.Rows(`{"resource_group": "default"}`)) } func testResourceGroupNameFromIS(t *testing.T, ctx sessionctx.Context, name string) *model.ResourceGroupInfo { diff --git a/ddl/resourcegroup/group.go b/ddl/resourcegroup/group.go index 0023787cc777..17c4a0afd407 100644 --- a/ddl/resourcegroup/group.go +++ b/ddl/resourcegroup/group.go @@ -21,14 +21,15 @@ import ( "k8s.io/apimachinery/pkg/api/resource" ) -const maxGroupNameLength = 32 +// MaxGroupNameLength is max length of the name of a resource group +const MaxGroupNameLength = 32 // NewGroupFromOptions creates a new resource group from the given options. func NewGroupFromOptions(groupName string, options *model.ResourceGroupSettings) (*rmpb.ResourceGroup, error) { if options == nil { return nil, ErrInvalidGroupSettings } - if len(groupName) > maxGroupNameLength { + if len(groupName) > MaxGroupNameLength { return nil, ErrTooLongResourceGroupName } group := &rmpb.ResourceGroup{ diff --git a/domain/domain_sysvars.go b/domain/domain_sysvars.go index 6988cedcc9b5..3d102687454d 100644 --- a/domain/domain_sysvars.go +++ b/domain/domain_sysvars.go @@ -76,7 +76,6 @@ func (do *Domain) setGlobalResourceControl(enable bool) { } else { variable.DisableGlobalResourceControlFunc() } - logutil.BgLogger().Info("set resource control", zap.Bool("enable", enable)) } // updatePDClient is used to set the dynamic option into the PD client. diff --git a/executor/BUILD.bazel b/executor/BUILD.bazel index c8881bec7091..4eaeffdfb3c4 100644 --- a/executor/BUILD.bazel +++ b/executor/BUILD.bazel @@ -214,6 +214,7 @@ go_library( "@com_github_pingcap_kvproto//pkg/encryptionpb", "@com_github_pingcap_kvproto//pkg/kvrpcpb", "@com_github_pingcap_kvproto//pkg/metapb", + "@com_github_pingcap_kvproto//pkg/resource_manager", "@com_github_pingcap_kvproto//pkg/tikvpb", "@com_github_pingcap_log//:log", "@com_github_pingcap_sysutil//:sysutil", diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index d0b3afa4e536..39666333762a 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -30,6 +30,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/failpoint" "github.com/pingcap/kvproto/pkg/deadlock" + rmpb "github.com/pingcap/kvproto/pkg/resource_manager" "github.com/pingcap/tidb/ddl/label" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/domain/infosync" @@ -185,7 +186,7 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex case infoschema.ClusterTableMemoryUsageOpsHistory: err = e.setDataForClusterMemoryUsageOpsHistory(sctx) case infoschema.TableResourceGroups: - err = e.setDataFromResourceGroups(sctx) + err = e.setDataFromResourceGroups() } if err != nil { return nil, err @@ -3388,17 +3389,37 @@ func (e *memtableRetriever) setDataFromPlacementPolicies(sctx sessionctx.Context return nil } -func (e *memtableRetriever) setDataFromResourceGroups(sctx sessionctx.Context) error { - is := sessiontxn.GetTxnManager(sctx).GetTxnInfoSchema() - resourceGroups := is.AllResourceGroups() +func (e *memtableRetriever) setDataFromResourceGroups() error { + resourceGroups, err := infosync.GetAllResourceGroups(context.TODO()) + if err != nil { + return errors.Errorf("failed to access resource group manager, error message is %s", err.Error()) + } rows := make([][]types.Datum, 0, len(resourceGroups)) for _, group := range resourceGroups { - row := types.MakeDatums( - group.ID, - group.Name.O, - group.RURate, - ) - rows = append(rows, row) + //mode := "" + burstable := "NO" + switch group.Mode { + case rmpb.GroupMode_RUMode: + if group.RUSettings.RU.Settings.BurstLimit < 0 { + burstable = "YES" + } + row := types.MakeDatums( + group.Name, + group.RUSettings.RU.Settings.FillRate, + uint64(group.RUSettings.RU.Tokens), + burstable, + ) + rows = append(rows, row) + default: + //mode = "UNKNOWN_MODE" + row := types.MakeDatums( + group.Name, + nil, + nil, + nil, + ) + rows = append(rows, row) + } } e.rows = rows return nil diff --git a/executor/simple.go b/executor/simple.go index 2beab893bb5f..e291e42e0422 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -1090,24 +1090,23 @@ func (e *SimpleExec) executeCreateUser(ctx context.Context, s *ast.CreateUserStm userAttributes = append(userAttributes, fmt.Sprintf("\"metadata\": %s", s.CommentOrAttributeOption.Value)) } } - resourceGroupName := "default" + if s.ResourceGroupNameOption != nil { if !variable.EnableResourceControl.Load() { return infoschema.ErrResourceGroupSupportDisabled } - if s.ResourceGroupNameOption.Type == ast.UserResourceGroupName { - resourceGroupName = s.ResourceGroupNameOption.Value - } + + resourceGroupName := strings.ToLower(s.ResourceGroupNameOption.Value) // check if specified resource group exists if resourceGroupName != "default" && resourceGroupName != "" { _, exists := e.is.ResourceGroupByName(model.NewCIStr(resourceGroupName)) if !exists { - return infoschema.ErrResourceGroupNotExists + return infoschema.ErrResourceGroupNotExists.GenWithStackByArgs(resourceGroupName) } } + userAttributes = append(userAttributes, fmt.Sprintf("\"resource_group\": \"%s\"", resourceGroupName)) } - userAttributes = append(userAttributes, fmt.Sprintf("\"resource_group\": \"%s\"", resourceGroupName)) // If FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME are both specified to 0, a string of 0 length is generated. // When inserting the attempts into json, an error occurs. This requires special handling. if PasswordLocking != "" { @@ -1904,20 +1903,21 @@ func (e *SimpleExec) executeAlterUser(ctx context.Context, s *ast.AlterUserStmt) newAttributes = append(newAttributes, fmt.Sprintf(`"metadata": %s`, s.CommentOrAttributeOption.Value)) } } - if s.ResourceGroupNameOption != nil && s.ResourceGroupNameOption.Type == ast.UserResourceGroupName { + if s.ResourceGroupNameOption != nil { if !variable.EnableResourceControl.Load() { return infoschema.ErrResourceGroupSupportDisabled } // check if specified resource group exists - if s.ResourceGroupNameOption.Value != "default" && s.ResourceGroupNameOption.Value != "" { - _, exists := e.is.ResourceGroupByName(model.NewCIStr(s.ResourceGroupNameOption.Value)) + resourceGroupName := strings.ToLower(s.ResourceGroupNameOption.Value) + if resourceGroupName != "default" && s.ResourceGroupNameOption.Value != "" { + _, exists := e.is.ResourceGroupByName(model.NewCIStr(resourceGroupName)) if !exists { - return infoschema.ErrResourceGroupNotExists + return infoschema.ErrResourceGroupNotExists.GenWithStackByArgs(resourceGroupName) } } - newAttributes = append(newAttributes, fmt.Sprintf(`"resource_group": "%s"`, s.ResourceGroupNameOption.Value)) + newAttributes = append(newAttributes, fmt.Sprintf(`"resource_group": "%s"`, resourceGroupName)) } if passwordLockingStr != "" { newAttributes = append(newAttributes, passwordLockingStr) diff --git a/executor/simple_test.go b/executor/simple_test.go index 31f2b719d84b..0ededa68e225 100644 --- a/executor/simple_test.go +++ b/executor/simple_test.go @@ -94,9 +94,9 @@ func TestUserAttributes(t *testing.T) { _, err := rootTK.Exec(`CREATE USER testuser2 ATTRIBUTE '{"name": "Tom", age: 19}'`) rootTK.MustExec(`CREATE USER testuser2`) require.Error(t, err) - rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser'`).Check(testkit.Rows(`{"metadata": {"comment": "1234"}, "resource_group": "default"}`)) - rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser1'`).Check(testkit.Rows(`{"metadata": {"age": 19, "name": "Tom"}, "resource_group": "default"}`)) - rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser2'`).Check(testkit.Rows(`{"resource_group": "default"}`)) + rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser'`).Check(testkit.Rows(`{"metadata": {"comment": "1234"}}`)) + rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser1'`).Check(testkit.Rows(`{"metadata": {"age": 19, "name": "Tom"}}`)) + rootTK.MustQuery(`SELECT user_attributes FROM mysql.user WHERE user = 'testuser2'`).Check(testkit.Rows(`{}`)) rootTK.MustQueryWithContext(ctx, `SELECT attribute FROM information_schema.user_attributes WHERE user = 'testuser'`).Check(testkit.Rows(`{"comment": "1234"}`)) rootTK.MustQueryWithContext(ctx, `SELECT attribute FROM information_schema.user_attributes WHERE user = 'testuser1'`).Check(testkit.Rows(`{"age": 19, "name": "Tom"}`)) rootTK.MustQueryWithContext(ctx, `SELECT attribute->>"$.age" AS age, attribute->>"$.name" AS name FROM information_schema.user_attributes WHERE user = 'testuser1'`).Check(testkit.Rows(`19 Tom`)) @@ -127,7 +127,7 @@ func TestUserAttributes(t *testing.T) { // https://github.com/pingcap/tidb/issues/39207 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.MustQuery("select user_attributes from mysql.user where user = 'usr1'").Check(testkit.Rows(`{"metadata": {"comment": "comment1"}}`)) rootTK.MustExec("set global tidb_enable_resource_control = 'on'") rootTK.MustExec("CREATE RESOURCE GROUP rg1 ru_per_sec = 100") rootTK.MustExec("alter user usr1 resource group rg1") diff --git a/executor/simpletest/password_management_test.go b/executor/simpletest/password_management_test.go index ae3352cdf84b..1e79662b5d5a 100644 --- a/executor/simpletest/password_management_test.go +++ b/executor/simpletest/password_management_test.go @@ -407,11 +407,11 @@ func TestFailedLoginTrackingBasic(t *testing.T) { testkit.Rows("CREATE USER 'u8'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME UNBOUNDED")) tk.MustExec("ALTER USER 'u4'@'localhost' PASSWORD_LOCK_TIME 0 FAILED_LOGIN_ATTEMPTS 0") - tk.MustQuery("select user_attributes from mysql.user where user = 'u4' and host = 'localhost'").Check(testkit.Rows(`{"resource_group": "default"}`)) + tk.MustQuery("select user_attributes from mysql.user where user = 'u4' and host = 'localhost'").Check(testkit.Rows(``)) tk.MustExec("ALTER USER 'u4'@'localhost' account unlock") - tk.MustQuery("select user_attributes from mysql.user where user = 'u4' and host = 'localhost'").Check(testkit.Rows(`{"resource_group": "default"}`)) + tk.MustQuery("select user_attributes from mysql.user where user = 'u4' and host = 'localhost'").Check(testkit.Rows(``)) tk.MustExec("ALTER USER 'u4'@'localhost' PASSWORD_LOCK_TIME 6") - tk.MustQuery("select user_attributes from mysql.user where user = 'u4' and host = 'localhost'").Check(testkit.Rows(`{"Password_locking": {"failed_login_attempts": 0, "password_lock_time_days": 6}, "resource_group": "default"}`)) + tk.MustQuery("select user_attributes from mysql.user where user = 'u4' and host = 'localhost'").Check(testkit.Rows(`{"Password_locking": {"failed_login_attempts": 0, "password_lock_time_days": 6}}`)) } func TestUserReuseControl(t *testing.T) { @@ -748,7 +748,7 @@ func TestFailedLoginTracking(t *testing.T) { // Set FAILED_LOGIN_ATTEMPTS to 1, and check error messages after login failure once. createAndCheck(tk, "CREATE USER 'testu1'@'localhost' IDENTIFIED BY 'testu1' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME 1", - "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 1}, \"resource_group\": \"default\"}", "testu1") + "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 1}}", "testu1") err := tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, sha1Password("password"), nil) lds := strconv.FormatInt(1, 10) errTarget := privileges.GenerateAccountAutoLockErr(1, "testu1", "localhost", lds, lds) @@ -762,7 +762,7 @@ func TestFailedLoginTracking(t *testing.T) { // Set FAILED_LOGIN_ATTEMPTS to 1 and PASSWORD_LOCK_TIME to UNBOUNDED. Check error messages after failed login once. createAndCheck(tk, "CREATE USER 'testu2'@'localhost' IDENTIFIED BY 'testu2' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME UNBOUNDED", - "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": -1}, \"resource_group\": \"default\"}", "testu2") + "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": -1}}", "testu2") err = tk.Session().Auth(&auth.UserIdentity{Username: "testu2", Hostname: "localhost"}, sha1Password("password"), nil) errTarget = privileges.GenerateAccountAutoLockErr(1, "testu2", "localhost", "unlimited", "unlimited") require.Equal(t, err.Error(), errTarget.Error()) @@ -775,31 +775,31 @@ func TestFailedLoginTracking(t *testing.T) { // Set FAILED_LOGIN_ATTEMPTS to 0 or PASSWORD_LOCK_TIME to 0. Check error messages after failed login once. createAndCheck(tk, "CREATE USER 'testu3'@'localhost' IDENTIFIED BY 'testu3' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME UNBOUNDED", - "{\"Password_locking\": {\"failed_login_attempts\": 0, \"password_lock_time_days\": -1}, \"resource_group\": \"default\"}", "testu3") + "{\"Password_locking\": {\"failed_login_attempts\": 0, \"password_lock_time_days\": -1}}", "testu3") err = tk.Session().Auth(&auth.UserIdentity{Username: "testu3", Hostname: "localhost"}, sha1Password("password"), nil) require.ErrorContains(t, err, "Access denied for user 'testu3'@'localhost' (using password: YES)") checkAuthUser(t, tk, "testu3", 0, "") createAndCheck(tk, "CREATE USER 'testu4'@'localhost' IDENTIFIED BY 'testu4' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME 0", - "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 0}, \"resource_group\": \"default\"}", "testu4") + "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 0}}", "testu4") err = tk.Session().Auth(&auth.UserIdentity{Username: "testu4", Hostname: "localhost"}, sha1Password("password"), nil) require.ErrorContains(t, err, "Access denied for user 'testu4'@'localhost' (using password: YES)") checkAuthUser(t, tk, "testu4", 0, "") tk.MustExec("CREATE USER 'testu5'@'localhost' IDENTIFIED BY 'testu5' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME 0") err = tk.Session().Auth(&auth.UserIdentity{Username: "testu5", Hostname: "localhost"}, sha1Password("password"), nil) require.ErrorContains(t, err, "Access denied for user 'testu5'@'localhost' (using password: YES)") - tk.MustQuery("select user_attributes from mysql.user where user= 'testu5' and host = 'localhost'").Check(testkit.Rows("{\"resource_group\": \"default\"}")) + tk.MustQuery("select user_attributes from mysql.user where user= 'testu5' and host = 'localhost'").Check(testkit.Rows("{}")) tk.MustExec("DROP USER 'testu1'@'localhost', 'testu2'@'localhost', 'testu3'@'localhost', 'testu4'@'localhost', 'testu5'@'localhost'") // Create user specifying only comment. tk.MustExec("CREATE USER 'testu1'@'localhost' IDENTIFIED BY 'testu1' comment 'testcomment' ") tk.MustQuery("select user_attributes from mysql.user where user= 'testu1' and host = 'localhost'"). - Check(testkit.Rows("{\"metadata\": {\"comment\": \"testcomment\"}, \"resource_group\": \"default\"}")) + Check(testkit.Rows("{\"metadata\": {\"comment\": \"testcomment\"}}")) // Create user specifying only attribute. tk.MustExec("create user testu2@'localhost' identified by 'testu2' ATTRIBUTE '{\"attribute\":\"testattribute\"}'") tk.MustQuery("select user_attributes from mysql.user where user= 'testu2' and host = 'localhost'"). - Check(testkit.Rows("{\"metadata\": {\"attribute\": \"testattribute\"}, \"resource_group\": \"default\"}")) + Check(testkit.Rows("{\"metadata\": {\"attribute\": \"testattribute\"}}")) // Create user specified comment and FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME. tk.MustExec("create user testu3@'localhost' identified by 'testu3' FAILED_LOGIN_ATTEMPTS 1 " + @@ -932,9 +932,9 @@ func TestFailedLoginTracking(t *testing.T) { rootk := testkit.NewTestKit(t, store) createAndCheck(tk, "CREATE USER 'u6'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3", - "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 3}, \"resource_group\": \"default\"}", "u6") + "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 3}}", "u6") createAndCheck(tk, "CREATE USER 'u5'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 60 PASSWORD_LOCK_TIME 3", - "{\"Password_locking\": {\"failed_login_attempts\": 60, \"password_lock_time_days\": 3}, \"resource_group\": \"default\"}", "u5") + "{\"Password_locking\": {\"failed_login_attempts\": 60, \"password_lock_time_days\": 3}}", "u5") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) checkAuthUser(t, rootk, "u6", 1, "N") @@ -984,7 +984,7 @@ func TestFailedLoginTracking(t *testing.T) { checkAuthUser(t, rootk, "u6", 1, "N") createAndCheck(rootk, "CREATE USER 'u1'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 3", - "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 0}, \"resource_group\": \"default\"}", "u1") + "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 0}}", "u1") require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: "u6", Hostname: "localhost"}, sha1Password("password"), nil)) checkAuthUser(t, rootk, "u1", 0, "") alterAndCheck(t, rootk, "ALTER USER 'u1'@'localhost' PASSWORD_LOCK_TIME 6;", "u1", 3, 6, 0) @@ -999,18 +999,18 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { // Create user specifying only comment. tk.MustExec("CREATE USER 'testu1'@'localhost' IDENTIFIED BY 'testu1' comment 'testcomment' ") tk.MustQuery("select user_attributes from mysql.user where user= 'testu1' and host = 'localhost'"). - Check(testkit.Rows("{\"metadata\": {\"comment\": \"testcomment\"}, \"resource_group\": \"default\"}")) + Check(testkit.Rows("{\"metadata\": {\"comment\": \"testcomment\"}}")) tk.MustExec("Alter USER 'testu1'@'localhost' comment ''") tk.MustQuery("select user_attributes from mysql.user where user= 'testu1' and host = 'localhost'"). - Check(testkit.Rows("{\"metadata\": {\"comment\": \"\"}, \"resource_group\": \"default\"}")) + Check(testkit.Rows("{\"metadata\": {\"comment\": \"\"}}")) // Create user specifying only attribute. tk.MustExec("CREATE USER 'testu2'@'localhost' IDENTIFIED BY 'testu2' ATTRIBUTE '{\"attribute\":\"testattribute\"}'") tk.MustQuery("select user_attributes from mysql.user where user= 'testu2' and host = 'localhost'"). - Check(testkit.Rows("{\"metadata\": {\"attribute\": \"testattribute\"}, \"resource_group\": \"default\"}")) + Check(testkit.Rows("{\"metadata\": {\"attribute\": \"testattribute\"}}")) tk.MustExec("Alter USER 'testu2'@'localhost' ATTRIBUTE '{\"attribute\":\"test\"}'") tk.MustQuery("select user_attributes from mysql.user where user= 'testu2' and host = 'localhost'"). - Check(testkit.Rows("{\"metadata\": {\"attribute\": \"test\"}, \"resource_group\": \"default\"}")) + Check(testkit.Rows("{\"metadata\": {\"attribute\": \"test\"}}")) // Create a user and specify FAILED_LOGIN_ATTEMPTS, PASSWORD_LOCK_TIME, and COMMENT. // Check the user_attributes value after alter user. @@ -1074,7 +1074,7 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { checkUserUserAttributes(tk, "testu8", "localhost", "1 1 ") tk.MustExec("alter user 'testu8'@'localhost' FAILED_LOGIN_ATTEMPTS 0 PASSWORD_LOCK_TIME 0") tk.MustQuery("select user_attributes from mysql.user where user= 'testu8' and host = 'localhost'"). - Check(testkit.Rows("{\"resource_group\": \"default\"}")) + Check(testkit.Rows("")) // Specify only FAILED_LOGIN_ATTEMPTS one attribute when creating user. // Change the value to 0 and check the user_attributes value. @@ -1082,7 +1082,7 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { tk.MustQuery("select JSON_EXTRACT(user_attributes, '$.Password_locking.failed_login_attempts') " + "from mysql.user where user='testu9' and host ='localhost'").Check(testkit.Rows("1")) tk.MustExec("ALTER USER 'testu9'@'localhost' FAILED_LOGIN_ATTEMPTS 0") - tk.MustQuery("select user_attributes from mysql.user where user='testu9' and host ='localhost'").Check(testkit.Rows("{\"resource_group\": \"default\"}")) + tk.MustQuery("select user_attributes from mysql.user where user='testu9' and host ='localhost'").Check(testkit.Rows("")) // Specify only PASSWORD_LOCK_TIME one attribute when creating user. // Change the value to 0 and check the user_attributes value. @@ -1090,7 +1090,7 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { tk.MustQuery("select JSON_EXTRACT(user_attributes, '$.Password_locking.password_lock_time_days') " + "from mysql.user where user='testu10' and host ='localhost'").Check(testkit.Rows("1")) tk.MustExec("ALTER USER 'testu10'@'localhost' PASSWORD_LOCK_TIME 0") - tk.MustQuery("select user_attributes from mysql.user where user='testu10' and host ='localhost'").Check(testkit.Rows("{\"resource_group\": \"default\"}")) + tk.MustQuery("select user_attributes from mysql.user where user='testu10' and host ='localhost'").Check(testkit.Rows("")) // Specify FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME attributes when creating user , // change the values of the two attributes to 0, and check the value of user_attributes. @@ -1104,7 +1104,7 @@ func TestFailedLoginTrackingAlterUser(t *testing.T) { "from mysql.user where user='testu11' and host ='localhost'").Check(testkit.Rows("1 0")) tk.MustExec("ALTER USER 'testu11'@'localhost' FAILED_LOGIN_ATTEMPTS 0") tk.MustQuery("select user_attributes " + - "from mysql.user where user='testu11' and host ='localhost'").Check(testkit.Rows("{\"resource_group\": \"default\"}")) + "from mysql.user where user='testu11' and host ='localhost'").Check(testkit.Rows("")) rootTK := testkit.NewTestKit(t, store) sql := new(strings.Builder) @@ -1165,7 +1165,7 @@ func TestFailedLoginTrackingCheckPrivilges(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) createAndCheck(tk, "CREATE USER 'testu1'@'localhost' IDENTIFIED BY '' FAILED_LOGIN_ATTEMPTS 1 PASSWORD_LOCK_TIME 1", - "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 1}, \"resource_group\": \"default\"}", "testu1") + "{\"Password_locking\": {\"failed_login_attempts\": 1, \"password_lock_time_days\": 1}}", "testu1") require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "testu1", Hostname: "localhost"}, nil, nil)) // Specify FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME attributes when creating user , // Check user privileges after successful login. @@ -1192,7 +1192,7 @@ func TestUserPassword(t *testing.T) { "CREATE USER 'u1'@'localhost' IDENTIFIED BY '!@#HASHhs123' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 4;", "u1", "localhost", - "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 4}, \"resource_group\": \"default\"}", + "{\"Password_locking\": {\"failed_login_attempts\": 3, \"password_lock_time_days\": 4}}", "qwe123", "!@#HASHhs123", }, @@ -1201,7 +1201,7 @@ func TestUserPassword(t *testing.T) { `CREATE USER 'u2'@'localhost' IDENTIFIED BY '!@#HASHhs123' FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 3 COMMENT 'Some statements to test create user'`, "u2", "localhost", - "{\"Password_locking\": {\"failed_login_attempts\": 4, \"password_lock_time_days\": 3}, \"metadata\": {\"comment\": \"Some statements to test create user\"}, \"resource_group\": \"default\"}", + "{\"Password_locking\": {\"failed_login_attempts\": 4, \"password_lock_time_days\": 3}, \"metadata\": {\"comment\": \"Some statements to test create user\"}}", "qwe123", "!@#HASHhs123", }, @@ -1227,7 +1227,7 @@ func TestPasswordExpiredAndTacking(t *testing.T) { require.Error(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("qwe123"), nil)) tk = testkit.NewTestKit(t, store) createAndCheck(tk, `CREATE USER 'u3'@'localhost' IDENTIFIED BY '!@#HASHhs123' PASSWORD EXPIRE INTERVAL 3 DAY FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 3 COMMENT 'Some statements to test create user'`, - "{\"Password_locking\": {\"failed_login_attempts\": 4, \"password_lock_time_days\": 3}, \"metadata\": {\"comment\": \"Some statements to test create user\"}, \"resource_group\": \"default\"}", user) + "{\"Password_locking\": {\"failed_login_attempts\": 4, \"password_lock_time_days\": 3}, \"metadata\": {\"comment\": \"Some statements to test create user\"}}", user) require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: user, Hostname: host}, sha1Password("!@#HASHhs123"), nil)) tk = testkit.NewTestKit(t, store) diff --git a/infoschema/BUILD.bazel b/infoschema/BUILD.bazel index f827394be790..20a4f150e4a2 100644 --- a/infoschema/BUILD.bazel +++ b/infoschema/BUILD.bazel @@ -17,6 +17,7 @@ go_library( deps = [ "//config", "//ddl/placement", + "//ddl/resourcegroup", "//domain/infosync", "//errno", "//kv", diff --git a/infoschema/tables.go b/infoschema/tables.go index a38319a05c63..3cbf9ee1b464 100644 --- a/infoschema/tables.go +++ b/infoschema/tables.go @@ -32,6 +32,7 @@ import ( "github.com/pingcap/log" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl/placement" + "github.com/pingcap/tidb/ddl/resourcegroup" "github.com/pingcap/tidb/domain/infosync" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta/autoid" @@ -824,6 +825,7 @@ var tableProcesslistCols = []columnInfo{ {name: "MEM", tp: mysql.TypeLonglong, size: 21, flag: mysql.UnsignedFlag}, {name: "DISK", tp: mysql.TypeLonglong, size: 21, flag: mysql.UnsignedFlag}, {name: "TxnStart", tp: mysql.TypeVarchar, size: 64, flag: mysql.NotNullFlag, deflt: ""}, + {name: "RESOURCE_GROUP", tp: mysql.TypeVarchar, size: resourcegroup.MaxGroupNameLength, flag: mysql.NotNullFlag, deflt: ""}, } var tableTiDBIndexesCols = []columnInfo{ @@ -1591,10 +1593,10 @@ var tableMemoryUsageOpsHistoryCols = []columnInfo{ } var tableResourceGroupsCols = []columnInfo{ - {name: "GROUP_ID", tp: mysql.TypeLonglong, size: 64, flag: mysql.NotNullFlag}, - {name: "GROUP_NAME", tp: mysql.TypeVarchar, size: 512, flag: mysql.NotNullFlag}, - {name: "RU_PER_SECOND", tp: mysql.TypeLonglong, size: 64}, - // {name: "BURSTABLE", tp: mysql.TypeVarchar, size: 10}, + {name: "NAME", tp: mysql.TypeVarchar, size: resourcegroup.MaxGroupNameLength, flag: mysql.NotNullFlag}, + {name: "RU_PER_SEC", tp: mysql.TypeLonglong, size: 21}, + {name: "RU_TOKENS", tp: mysql.TypeLonglong, size: 21}, + {name: "BURSTABLE", tp: mysql.TypeVarchar, size: 3}, } // GetShardingInfo returns a nil or description string for the sharding information of given TableInfo. diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index f796345bbd8e..d44721090b8b 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -161,7 +161,8 @@ func TestInfoSchemaFieldValue(t *testing.T) { " `DIGEST` varchar(64) DEFAULT '',\n" + " `MEM` bigint(21) unsigned DEFAULT NULL,\n" + " `DISK` bigint(21) unsigned DEFAULT NULL,\n" + - " `TxnStart` varchar(64) NOT NULL DEFAULT ''\n" + + " `TxnStart` varchar(64) NOT NULL DEFAULT '',\n" + + " `RESOURCE_GROUP` varchar(32) NOT NULL DEFAULT ''\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) tk.MustQuery("show create table information_schema.cluster_log").Check( testkit.Rows("" + @@ -303,47 +304,50 @@ func TestSomeTables(t *testing.T) { tk.SetSession(se) sm := &testkit.MockSessionManager{PS: make([]*util.ProcessInfo, 0)} sm.PS = append(sm.PS, &util.ProcessInfo{ - ID: 1, - User: "user-1", - Host: "localhost", - Port: "", - DB: "information_schema", - Command: byte(1), - Digest: "abc1", - State: 1, - Info: "do something", - StmtCtx: tk.Session().GetSessionVars().StmtCtx, + ID: 1, + User: "user-1", + Host: "localhost", + Port: "", + DB: "information_schema", + Command: byte(1), + Digest: "abc1", + State: 1, + Info: "do something", + StmtCtx: tk.Session().GetSessionVars().StmtCtx, + ResourceGroupName: "rg1", }) sm.PS = append(sm.PS, &util.ProcessInfo{ - ID: 2, - User: "user-2", - Host: "localhost", - Port: "", - DB: "test", - Command: byte(2), - Digest: "abc2", - State: 2, - Info: strings.Repeat("x", 101), - StmtCtx: tk.Session().GetSessionVars().StmtCtx, + ID: 2, + User: "user-2", + Host: "localhost", + Port: "", + DB: "test", + Command: byte(2), + Digest: "abc2", + State: 2, + Info: strings.Repeat("x", 101), + StmtCtx: tk.Session().GetSessionVars().StmtCtx, + ResourceGroupName: "rg2", }) sm.PS = append(sm.PS, &util.ProcessInfo{ - ID: 3, - User: "user-3", - Host: "127.0.0.1", - Port: "12345", - DB: "test", - Command: byte(2), - Digest: "abc3", - State: 1, - Info: "check port", - StmtCtx: tk.Session().GetSessionVars().StmtCtx, + ID: 3, + User: "user-3", + Host: "127.0.0.1", + Port: "12345", + DB: "test", + Command: byte(2), + Digest: "abc3", + State: 1, + Info: "check port", + StmtCtx: tk.Session().GetSessionVars().StmtCtx, + ResourceGroupName: "rg3", }) tk.Session().SetSessionManager(sm) tk.MustQuery("select * from information_schema.PROCESSLIST order by ID;").Sort().Check( testkit.Rows( - fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 %s %s abc1 0 0 ", "in transaction", "do something"), - fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 %s %s abc2 0 0 ", "autocommit", strings.Repeat("x", 101)), - fmt.Sprintf("3 user-3 127.0.0.1:12345 test Init DB 9223372036 %s %s abc3 0 0 ", "in transaction", "check port"), + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 %s %s abc1 0 0 rg1", "in transaction", "do something"), + fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 %s %s abc2 0 0 rg2", "autocommit", strings.Repeat("x", 101)), + fmt.Sprintf("3 user-3 127.0.0.1:12345 test Init DB 9223372036 %s %s abc3 0 0 rg3", "in transaction", "check port"), )) tk.MustQuery("SHOW PROCESSLIST;").Sort().Check( testkit.Rows( @@ -360,30 +364,32 @@ func TestSomeTables(t *testing.T) { sm = &testkit.MockSessionManager{PS: make([]*util.ProcessInfo, 0)} sm.PS = append(sm.PS, &util.ProcessInfo{ - ID: 1, - User: "user-1", - Host: "localhost", - DB: "information_schema", - Command: byte(1), - Digest: "abc1", - State: 1, + ID: 1, + User: "user-1", + Host: "localhost", + DB: "information_schema", + Command: byte(1), + Digest: "abc1", + State: 1, + ResourceGroupName: "rg1", }) sm.PS = append(sm.PS, &util.ProcessInfo{ - ID: 2, - User: "user-2", - Host: "localhost", - Command: byte(2), - Digest: "abc2", - State: 2, - Info: strings.Repeat("x", 101), - CurTxnStartTS: 410090409861578752, + ID: 2, + User: "user-2", + Host: "localhost", + Command: byte(2), + Digest: "abc2", + State: 2, + Info: strings.Repeat("x", 101), + CurTxnStartTS: 410090409861578752, + ResourceGroupName: "rg2", }) tk.Session().SetSessionManager(sm) tk.Session().GetSessionVars().TimeZone = time.UTC tk.MustQuery("select * from information_schema.PROCESSLIST order by ID;").Check( testkit.Rows( - fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 %s %s abc1 0 0 ", "in transaction", ""), - fmt.Sprintf("2 user-2 localhost Init DB 9223372036 %s %s abc2 0 0 07-29 03:26:05.158(410090409861578752)", "autocommit", strings.Repeat("x", 101)), + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 %s %s abc1 0 0 rg1", "in transaction", ""), + fmt.Sprintf("2 user-2 localhost Init DB 9223372036 %s %s abc2 0 0 07-29 03:26:05.158(410090409861578752) rg2", "autocommit", strings.Repeat("x", 101)), )) tk.MustQuery("SHOW PROCESSLIST;").Sort().Check( testkit.Rows( @@ -397,11 +403,11 @@ func TestSomeTables(t *testing.T) { )) tk.MustQuery("select * from information_schema.PROCESSLIST where db is null;").Check( testkit.Rows( - fmt.Sprintf("2 user-2 localhost Init DB 9223372036 %s %s abc2 0 0 07-29 03:26:05.158(410090409861578752)", "autocommit", strings.Repeat("x", 101)), + fmt.Sprintf("2 user-2 localhost Init DB 9223372036 %s %s abc2 0 0 07-29 03:26:05.158(410090409861578752) rg2", "autocommit", strings.Repeat("x", 101)), )) tk.MustQuery("select * from information_schema.PROCESSLIST where Info is null;").Check( testkit.Rows( - fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 %s %s abc1 0 0 ", "in transaction", ""), + fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 %s %s abc1 0 0 rg1", "in transaction", ""), )) } diff --git a/parser/ast/misc.go b/parser/ast/misc.go index 8d5ecd3fdb4d..eec57ae2a172 100644 --- a/parser/ast/misc.go +++ b/parser/ast/misc.go @@ -1584,15 +1584,12 @@ func (c *CommentOrAttributeOption) Restore(ctx *format.RestoreCtx) error { } type ResourceGroupNameOption struct { - Type int Value string } func (c *ResourceGroupNameOption) Restore(ctx *format.RestoreCtx) error { - if c.Type == UserResourceGroupName { - ctx.WriteKeyWord(" RESOURCE GROUP ") - ctx.WriteName(c.Value) - } + ctx.WriteKeyWord(" RESOURCE GROUP ") + ctx.WriteName(c.Value) return nil } diff --git a/parser/model/model.go b/parser/model/model.go index b154ef4dac65..b953b1140bf7 100644 --- a/parser/model/model.go +++ b/parser/model/model.go @@ -1880,7 +1880,7 @@ func (p *ResourceGroupSettings) Clone() *ResourceGroupSettings { return &cloned } -// ResourceGroupInfo is the struct to store the placement policy. +// ResourceGroupInfo is the struct to store the resource group. type ResourceGroupInfo struct { *ResourceGroupSettings ID int64 `json:"id"` diff --git a/parser/parser.go b/parser/parser.go index a463737e298d..6ac03e1139c6 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -21292,7 +21292,7 @@ yynewstate: } case 2381: { - parser.yyVAL.item = &ast.ResourceGroupNameOption{Type: ast.UserResourceGroupName, Value: yyS[yypt-0].ident} + parser.yyVAL.item = &ast.ResourceGroupNameOption{Value: yyS[yypt-0].ident} } case 2382: { diff --git a/parser/parser.y b/parser/parser.y index 6a2974a80122..abce90d9e3c7 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -13041,7 +13041,7 @@ ResourceGroupNameOption: } | "RESOURCE" "GROUP" ResourceGroupName { - $$ = &ast.ResourceGroupNameOption{Type: ast.UserResourceGroupName, Value: $3} + $$ = &ast.ResourceGroupNameOption{Value: $3} } PasswordOrLockOptions: diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 1bbfe0e85202..0040751e0ff9 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -1137,7 +1137,7 @@ func TestCreateDropUser(t *testing.T) { tk.MustExec(`DROP USER tcd3`) tk.MustExec(`CREATE USER usr1`) - tk.MustQuery(`SELECT User_attributes FROM mysql.user WHERE User = "usr1"`).Check(testkit.Rows("{\"resource_group\": \"default\"}")) + tk.MustQuery(`SELECT User_attributes FROM mysql.user WHERE User = "usr1"`).Check(testkit.Rows("{}")) tk.MustExec(`DROP USER usr1`) tk.MustExec("set global tidb_enable_resource_control = 'on'") diff --git a/session/session.go b/session/session.go index 13ac77ee421e..9f5197b8da5d 100644 --- a/session/session.go +++ b/session/session.go @@ -1574,6 +1574,7 @@ func (s *session) SetProcessInfo(sql string, t time.Time, command byte, maxExecu if explain, ok := p.(*plannercore.Explain); ok && explain.Analyze && explain.TargetPlan != nil { p = explain.TargetPlan } + pi := util.ProcessInfo{ ID: s.sessionVars.ConnectionID, Port: s.sessionVars.Port, @@ -1595,6 +1596,7 @@ func (s *session) SetProcessInfo(sql string, t time.Time, command byte, maxExecu MaxExecutionTime: maxExecutionTime, RedactSQL: s.sessionVars.EnableRedactLog, ProtectedTSList: &s.sessionVars.ProtectedTSList, + ResourceGroupName: s.sessionVars.ResourceGroupName, } oldPi := s.ShowProcess() if p == nil { diff --git a/sessionctx/variable/BUILD.bazel b/sessionctx/variable/BUILD.bazel index b178ccf0a95d..c1d6e0b8b965 100644 --- a/sessionctx/variable/BUILD.bazel +++ b/sessionctx/variable/BUILD.bazel @@ -68,6 +68,7 @@ go_library( "@org_golang_x_exp//maps", "@org_golang_x_exp//slices", "@org_uber_go_atomic//:atomic", + "@org_uber_go_zap//:zap", ], ) diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index d9f8f9407b7f..3da39a2ef80e 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -48,6 +48,7 @@ import ( tikvcfg "github.com/tikv/client-go/v2/config" tikvstore "github.com/tikv/client-go/v2/kv" atomic2 "go.uber.org/atomic" + "go.uber.org/zap" ) // All system variables declared here are ordered by their scopes, which follow the order of scopes below: @@ -2322,8 +2323,11 @@ var defaultSysVars = []*SysVar{ }, }, {Scope: ScopeGlobal, Name: TiDBEnableResourceControl, Value: BoolToOnOff(DefTiDBEnableResourceControl), Type: TypeBool, SetGlobal: func(ctx context.Context, vars *SessionVars, s string) error { - EnableResourceControl.Store(TiDBOptOn(s)) - (*SetGlobalResourceControl.Load())(TiDBOptOn(s)) + if TiDBOptOn(s) != EnableResourceControl.Load() { + EnableResourceControl.Store(TiDBOptOn(s)) + (*SetGlobalResourceControl.Load())(TiDBOptOn(s)) + logutil.BgLogger().Info("set resource control", zap.Bool("enable", TiDBOptOn(s))) + } return nil }, GetGlobal: func(ctx context.Context, vars *SessionVars) (string, error) { return BoolToOnOff(EnableResourceControl.Load()), nil diff --git a/util/gpool/gpool.go b/util/gpool/gpool.go index bd65eaca9f50..dce4eee53616 100644 --- a/util/gpool/gpool.go +++ b/util/gpool/gpool.go @@ -46,8 +46,8 @@ var ( // BasePool is base class of pool type BasePool struct { - name string lastTuneTs atomicutil.Time + name string generator atomic.Uint64 } diff --git a/util/gpool/spmc/spmcpool.go b/util/gpool/spmc/spmcpool.go index eaa10c3b9a53..35b258957fd6 100644 --- a/util/gpool/spmc/spmcpool.go +++ b/util/gpool/spmc/spmcpool.go @@ -38,23 +38,22 @@ import ( // TF is the type of the context getter. It is used to get a context. // if we don't need to use CT/TF, we can define CT as any and TF as NilContext. type Pool[T any, U any, C any, CT any, TF pooltask.Context[CT]] struct { + workerCache sync.Pool + lock sync.Locker + stopCh chan struct{} + consumerFunc func(T, C, CT) U + cond *sync.Cond + taskCh chan *pooltask.TaskBox[T, U, C, CT, TF] + workers *loopQueue[T, U, C, CT, TF] + options *Options gpool.BasePool - workerCache sync.Pool - workers *loopQueue[T, U, C, CT, TF] - lock sync.Locker - cond *sync.Cond - taskCh chan *pooltask.TaskBox[T, U, C, CT, TF] taskManager pooltask.TaskManager[T, U, C, CT, TF] - options *Options - stopCh chan struct{} - consumerFunc func(T, C, CT) U + waitingTask atomicutil.Uint32 capacity atomic.Int32 running atomic.Int32 state atomic.Int32 waiting atomic.Int32 // waiting is the number of goroutines that are waiting for the pool to be available. heartbeatDone atomic.Bool - - waitingTask atomicutil.Uint32 // waitingTask is the number of tasks that are waiting for the pool to be available. } // NewSPMCPool create a single producer, multiple consumer goroutine pool. diff --git a/util/processinfo.go b/util/processinfo.go index dee4f4ea30a5..135b1c58d567 100644 --- a/util/processinfo.go +++ b/util/processinfo.go @@ -64,6 +64,7 @@ type ProcessInfo struct { User string Info string Port string + ResourceGroupName string PlanExplainRows [][]string OOMAlarmVariablesInfo OOMAlarmVariablesInfo ID uint64 @@ -135,7 +136,7 @@ func (pi *ProcessInfo) ToRow(tz *time.Location) []interface{} { diskConsumed = pi.DiskTracker.BytesConsumed() } } - return append(pi.ToRowForShow(true), pi.Digest, bytesConsumed, diskConsumed, pi.txnStartTs(tz)) + return append(pi.ToRowForShow(true), pi.Digest, bytesConsumed, diskConsumed, pi.txnStartTs(tz), pi.ResourceGroupName) } // GetMinStartTS returns the minimum start-ts (used to delay GC) that greater than `lowerBound` (0 if no such one).