MySQL高阶讲座之：`MySQL`的`Resource Groups`：其在多租户环境下的`CPU/IO`隔离。

admin
Wed, 20 Aug 2025 11:27:41 +0000
Mysql, groups, mysql, resource

各位老铁，早上好/下午好/晚上好！ 今天咱们来聊聊MySQL里一个听起来有点高大上，但实际上很接地气的功能：Resource Groups。这玩意儿，就像你家里的电闸开关，可以控制不同房间的用电量，避免一个房间电器开太多把整个家都给搞停电了。在MySQL里，它能控制不同用户的CPU和IO资源，尤其是在多租户环境下，简直是救命稻草。 咱们先来了解一下，啥是多租户环境？简单来说，就是一台MySQL服务器上跑着好几个不同的应用，每个应用都相当于一个“租户”。 如果其中一个租户突然发疯，执行了一个超慢的查询，或者疯狂写入数据，那就会把整个服务器的资源都占满了，导致其他租户的应用也跟着卡顿，甚至直接崩掉。 这可就麻烦大了！ 所以，Resource Groups就派上用场了。它可以把不同的租户分配到不同的资源组里，然后限制每个资源组可以使用的CPU和IO资源，这样就能保证每个租户都能分到一定的资源，避免一个租户把所有资源都抢走。 接下来，咱们就来一步一步地看看怎么使用Resource Groups。 第一步：创建Resource Group 创建Resource Group的语法很简单： CREA …

继续阅读“MySQL高阶讲座之：`MySQL`的`Resource Groups`：其在多租户环境下的`CPU/IO`隔离。”

The post MySQL高阶讲座之：`MySQL`的`Resource Groups`：其在多租户环境下的`CPU/IO`隔离。 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

各位老铁，早上好/下午好/晚上好！

今天咱们来聊聊MySQL里一个听起来有点高大上，但实际上很接地气的功能：Resource Groups。这玩意儿，就像你家里的电闸开关，可以控制不同房间的用电量，避免一个房间电器开太多把整个家都给搞停电了。在MySQL里，它能控制不同用户的CPU和IO资源，尤其是在多租户环境下，简直是救命稻草。

咱们先来了解一下，啥是多租户环境？简单来说，就是一台MySQL服务器上跑着好几个不同的应用，每个应用都相当于一个“租户”。 如果其中一个租户突然发疯，执行了一个超慢的查询，或者疯狂写入数据，那就会把整个服务器的资源都占满了，导致其他租户的应用也跟着卡顿，甚至直接崩掉。 这可就麻烦大了！

所以，Resource Groups就派上用场了。它可以把不同的租户分配到不同的资源组里，然后限制每个资源组可以使用的CPU和IO资源，这样就能保证每个租户都能分到一定的资源，避免一个租户把所有资源都抢走。

接下来，咱们就来一步一步地看看怎么使用Resource Groups。

第一步：创建Resource Group

创建Resource Group的语法很简单：

CREATE RESOURCE GROUP rg_name
  TYPE = SYSTEM | USER
  [VCPU = vcpu_count]
  [IO_PRIORITY = io_priority]
  [ENABLE | DISABLE];

rg_name: 你要创建的资源组的名字，随便起，但是最好起个有意义的，方便以后管理。

TYPE: 资源组的类型，有两种：SYSTEM和USER。SYSTEM资源组是给MySQL内部线程用的，USER资源组是给用户线程用的。 我们一般用USER类型。

VCPU: 这个资源组可以使用多少个CPU核心。 注意，这里的vcpu_count并不是绝对的CPU核心数，而是一个权重值。 比如，你有8个CPU核心，你可以把两个资源组的VCPU都设为1，这样每个资源组就能用到大约一半的CPU资源。 如果你把一个资源组的VCPU设为2，另一个设为1，那么第一个资源组就能用到大约三分之二的CPU资源。

IO_PRIORITY: 这个资源组的IO优先级。 有LOW, MEDIUM, HIGH三种级别。 优先级越高，这个资源组的IO请求就越先被处理。

ENABLE | DISABLE: 启用或禁用这个资源组。

举个例子，假设咱们有两个租户：租户A和租户B。 我们可以给租户A创建一个资源组rg_tenant_a，给租户B创建一个资源组rg_tenant_b。

CREATE RESOURCE GROUP rg_tenant_a
  TYPE = USER
  VCPU = 2
  IO_PRIORITY = MEDIUM
  ENABLE;

CREATE RESOURCE GROUP rg_tenant_b
  TYPE = USER
  VCPU = 1
  IO_PRIORITY = LOW
  ENABLE;

上面的代码表示：

rg_tenant_a资源组是用户类型的，可以使用2个CPU核心的资源，IO优先级是中等，并且已经启用。

rg_tenant_b资源组是用户类型的，可以使用1个CPU核心的资源，IO优先级是低，并且已经启用。

第二步：将用户分配到Resource Group

创建好资源组之后，咱们需要把用户分配到对应的资源组里。 这样，用户执行的查询和写入操作才会受到资源组的限制。

分配用户的语法也很简单：

SET RESOURCE GROUP rg_name FOR user;

rg_name: 你要分配的资源组的名字。

user: 你要分配的用户。 可以是单个用户，也可以是多个用户。

举个例子，假设咱们有两个用户：user_a和user_b。 我们可以把user_a分配到rg_tenant_a资源组，把user_b分配到rg_tenant_b资源组。

SET RESOURCE GROUP rg_tenant_a FOR 'user_a'@'%';
SET RESOURCE GROUP rg_tenant_b FOR 'user_b'@'%';

上面的代码表示：

把user_a用户分配到rg_tenant_a资源组。 注意，这里的'user_a'@'%'表示允许user_a从任何主机连接到MySQL服务器。

把user_b用户分配到rg_tenant_b资源组。

第三步：查看Resource Group信息

创建好资源组，并把用户分配到资源组之后，咱们可以查看一下Resource Group的信息，确认是否配置正确。

查看Resource Group信息的语法是：

SELECT * FROM performance_schema.resource_groups;
SELECT * FROM performance_schema.threads;

performance_schema.resource_groups: 这个表包含了所有Resource Group的信息，比如名字、类型、CPU权重、IO优先级等等。

performance_schema.threads: 这个表包含了所有线程的信息，包括线程所属的Resource Group。

举个例子，我们可以执行以下SQL语句来查看rg_tenant_a资源组的信息：

SELECT * FROM performance_schema.resource_groups WHERE RESOURCE_GROUP_NAME = 'rg_tenant_a';

执行结果类似：

RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_VCPU | RESOURCE_GROUP_IO | RESOURCE_GROUP_ENABLE
rg_tenant_a | USER | 2 | MEDIUM | YES

我们还可以执行以下SQL语句来查看user_a用户所属的Resource Group：

SELECT THREAD_ID, NAME, RESOURCE_GROUP FROM performance_schema.threads WHERE INSTR(NAME, 'user_a') > 0;

执行结果类似：

THREAD_ID | NAME | RESOURCE_GROUP
123 | thread/sql/main | rg_tenant_a

Resource Group 的一些高级用法和注意事项

1. 动态调整 Resource Group 的资源限制

Resource Group 的一个优点是，你可以动态地调整它的资源限制，而不需要重启 MySQL 服务器。 这在你需要临时增加或减少某个租户的资源时非常有用。

例如，如果你想临时增加 rg_tenant_a 资源组的 CPU 权重，你可以执行以下 SQL 语句：

ALTER RESOURCE GROUP rg_tenant_a VCPU = 3;

2. Resource Group 与连接池

如果你使用了连接池，你需要确保连接池中的连接都属于同一个 Resource Group。 否则，可能会导致资源分配不均。

3. Resource Group 与存储引擎

Resource Group 主要控制 CPU 和 IO 资源。 存储引擎本身也可能会有一些资源限制机制。 你需要根据你的存储引擎的特性来合理配置 Resource Group。

4. 监控 Resource Group 的资源使用情况

你可以使用 MySQL 的 Performance Schema 来监控 Resource Group 的资源使用情况。 例如，你可以查看每个 Resource Group 的 CPU 使用率、IO 吞吐量等指标。

5. 默认 Resource Group

MySQL 8.0 默认会创建一个名为 SYSTEM 的 Resource Group, 用于 MySQL 系统线程。未分配任何 Resource Group 的用户线程，默认会使用 default Resource Group。 可以通过设置 default_resource_group 系统变量来修改默认的 Resource Group。

6. Resource Group 的优先级

当多个用户线程同时竞争资源时，Resource Group 的优先级会影响资源的分配。 IO 优先级高的 Resource Group 会优先获得 IO 资源。 CPU 权重高的 Resource Group 会优先获得 CPU 资源。

Resource Group 的一些使用场景

多租户 SaaS 应用

这是 Resource Group 最常见的应用场景。 你可以使用 Resource Group 来隔离不同的租户，保证每个租户都能获得一定的资源，避免一个租户影响其他租户的性能。

数据库测试环境

你可以在数据库测试环境中使用 Resource Group 来模拟不同的负载情况。 例如，你可以创建一个 Resource Group 来模拟高负载的场景，然后测试你的应用程序在高负载下的性能。

数据库备份和恢复

在数据库备份和恢复过程中，可能会占用大量的 CPU 和 IO 资源。 你可以使用 Resource Group 来限制备份和恢复操作的资源使用，避免影响其他应用程序的性能。

Resource Group 的一些缺点

配置复杂

Resource Group 的配置相对复杂，需要对 MySQL 的内部机制有一定的了解。

性能开销

Resource Group 会带来一定的性能开销。 在资源竞争不激烈的情况下，Resource Group 的性能开销可能大于它带来的好处。

无法完全隔离

Resource Group 只能控制 CPU 和 IO 资源。 无法完全隔离内存、网络等资源。

总结

Resource Groups是MySQL提供的一个强大的资源管理工具，特别是在多租户环境下，它可以有效地隔离不同用户的资源使用，避免资源竞争导致性能问题。 但是，Resource Groups的配置相对复杂，需要对MySQL的内部机制有一定的了解。 在使用Resource Groups之前，需要仔细评估其带来的好处和坏处，并根据实际情况进行配置。

一些小技巧和注意事项

避免过度配置： 不要创建过多的 Resource Group。 过多的 Resource Group 会增加配置的复杂性，并可能导致性能问题。

监控资源使用情况： 定期监控 Resource Group 的资源使用情况，及时调整配置，避免资源浪费或资源不足。

测试配置： 在生产环境中使用 Resource Group 之前，务必在测试环境中进行充分的测试，确保配置正确，并且不会对应用程序的性能产生负面影响。

代码示例：模拟资源竞争和 Resource Group 的效果

为了更直观地展示 Resource Group 的效果，我们可以模拟一个资源竞争的场景，然后使用 Resource Group 来解决这个问题。

首先，我们创建两个用户：user_a 和 user_b， 并分别分配到 rg_tenant_a 和 rg_tenant_b 资源组。

CREATE USER 'user_a'@'%' IDENTIFIED BY 'password';
CREATE USER 'user_b'@'%' IDENTIFIED BY 'password';

GRANT ALL PRIVILEGES ON *.* TO 'user_a'@'%';
GRANT ALL PRIVILEGES ON *.* TO 'user_b'@'%';

FLUSH PRIVILEGES;

CREATE RESOURCE GROUP rg_tenant_a
  TYPE = USER
  VCPU = 1
  IO_PRIORITY = MEDIUM
  ENABLE;

CREATE RESOURCE GROUP rg_tenant_b
  TYPE = USER
  VCPU = 1
  IO_PRIORITY = LOW
  ENABLE;

SET RESOURCE GROUP rg_tenant_a FOR 'user_a'@'%';
SET RESOURCE GROUP rg_tenant_b FOR 'user_b'@'%';

然后，我们创建一个测试表 test_table，并插入一些数据。

CREATE TABLE test_table (
  id INT PRIMARY KEY AUTO_INCREMENT,
  data VARCHAR(255)
);

INSERT INTO test_table (data) VALUES
('data1'), ('data2'), ('data3'), ('data4'), ('data5'),
('data6'), ('data7'), ('data8'), ('data9'), ('data10');

接下来，我们分别用 user_a 和 user_b 连接到 MySQL 服务器，并执行以下操作：

user_a 执行一个 CPU 密集型的查询，例如：

SELECT SLEEP(10); -- 模拟一个耗时 10 秒的操作

user_b 执行一个 IO 密集型的查询，例如：

SELECT * FROM test_table WHERE data LIKE '%data%'; -- 模拟一个需要扫描大量数据的操作

在没有 Resource Group 的情况下，user_a 的 CPU 密集型查询可能会占用大量的 CPU 资源，导致 user_b 的 IO 密集型查询变得非常慢。

有了 Resource Group 之后，rg_tenant_a 和 rg_tenant_b 资源组会分别限制 user_a 和 user_b 的 CPU 资源使用，从而保证 user_b 的 IO 密集型查询也能获得一定的 CPU 资源，避免被 user_a 的 CPU 密集型查询完全阻塞。

你可以通过 SHOW PROCESSLIST; 命令来查看当前正在执行的查询，以及它们所属的 Resource Group。

最后，再强调几点：

Resource Groups 只是资源管理的一种方式，并不是万能的。 在使用 Resource Groups 的同时，还需要关注 SQL 语句的优化、索引的创建、数据库的参数配置等方面。

Resource Groups 的配置需要根据实际情况进行调整。 没有一种配置适用于所有场景。

希望今天的讲座对大家有所帮助！ 如果大家还有什么问题，欢迎随时提问。 谢谢大家！