MySQL高级讲座篇之：MySQL的`Resource Groups`如何防止恶意查询导致`CPU`和`IO`耗尽？

admin
Sun, 17 Aug 2025 11:42:33 +0000
Mysql, groups, mysql, resource

各位观众老爷们，大家好！今天咱就来聊聊MySQL里的一个“神器”——Resource Groups，看看它怎么帮咱们防止那些“吃CPU像吃辣条”的恶意查询，以及那些“狂刷IO像不要钱”的家伙，搞垮咱的数据库。 开场白：数据库的“地主老财”和“佃户” 想象一下，你的MySQL服务器就是一个地主老财，CPU和IO资源就是他家的田地。平时风调雨顺，一切安好。但总有些“佃户”（也就是查询）比较懒，种地效率低，占着田地不放，甚至还有些“恶意佃户”故意破坏田地，导致其他勤劳的“佃户”没地可种，最终大家都饿肚子（数据库性能下降）。 Resource Groups就是地主老财手里的“土地改革”方案，它可以把田地划成不同的“资源组”，给不同的“佃户”分配不同的田地，并且限制他们的“耕作方式”（CPU和IO使用）。这样，就算有些“恶意佃户”想破坏，也只能破坏自己那块地，影响不到其他人。 第一部分：Resource Groups是什么？能吃吗？ Resource Groups 是 MySQL 8.0 引入的一个功能，它允许咱们把线程分配到不同的资源组，并为每个资源组分配不同的 CPU 和 IO 优先级。简单 …

继续阅读“MySQL高级讲座篇之：MySQL的`Resource Groups`如何防止恶意查询导致`CPU`和`IO`耗尽？”

The post MySQL高级讲座篇之：MySQL的`Resource Groups`如何防止恶意查询导致`CPU`和`IO`耗尽？ first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

各位观众老爷们，大家好！今天咱就来聊聊MySQL里的一个“神器”——Resource Groups，看看它怎么帮咱们防止那些“吃CPU像吃辣条”的恶意查询，以及那些“狂刷IO像不要钱”的家伙，搞垮咱的数据库。

开场白：数据库的“地主老财”和“佃户”

想象一下，你的MySQL服务器就是一个地主老财，CPU和IO资源就是他家的田地。平时风调雨顺，一切安好。但总有些“佃户”（也就是查询）比较懒，种地效率低，占着田地不放，甚至还有些“恶意佃户”故意破坏田地，导致其他勤劳的“佃户”没地可种，最终大家都饿肚子（数据库性能下降）。

Resource Groups就是地主老财手里的“土地改革”方案，它可以把田地划成不同的“资源组”，给不同的“佃户”分配不同的田地，并且限制他们的“耕作方式”（CPU和IO使用）。这样，就算有些“恶意佃户”想破坏，也只能破坏自己那块地，影响不到其他人。

第一部分：Resource Groups是什么？能吃吗？

Resource Groups 是 MySQL 8.0 引入的一个功能，它允许咱们把线程分配到不同的资源组，并为每个资源组分配不同的 CPU 和 IO 优先级。简单来说，就是给不同的查询分配不同的“房间”，每个房间的资源不一样。

Resource Groups 的核心概念：

资源组（Resource Group）： 资源的集合，定义了 CPU 和 IO 优先级。

线程（Thread）： 执行 SQL 查询的线程。

资源组属性： 定义资源组的 CPU 亲和性、IO 优先级等。

为什么要用 Resource Groups？

资源隔离： 防止某些查询占用过多资源，影响其他查询。

QoS（服务质量）保证： 保证关键查询的性能。

资源限制： 限制某些查询的资源使用，防止恶意查询。

第二部分：Resource Groups 的“前世今生”：安装与配置

要用 Resource Groups，首先得确保你的 MySQL 版本是 8.0 及以上。然后，检查一下resource_group_enabled系统变量是否开启。

SHOW GLOBAL VARIABLES LIKE 'resource_group_enabled';

如果结果是OFF，那就需要开启它。

SET GLOBAL resource_group_enabled = ON;

创建资源组：

创建资源组的语法如下：

CREATE RESOURCE GROUP group_name
  TYPE = {SYSTEM | USER}
  [VCPU = (cpu_list)]
  [THREAD_PRIORITY = priority];

group_name：资源组的名称。

TYPE：资源组的类型。SYSTEM 类型的资源组只能由 MySQL 服务器内部使用，USER 类型的资源组可以由用户使用。

VCPU：指定资源组可以使用的 CPU 核心。

THREAD_PRIORITY：指定资源组的线程优先级。范围是 -20 到 19，数值越小优先级越高。

举个栗子：

创建一个名为high_priority的资源组，使用 CPU 核心 0 和 1，线程优先级为 -10。

CREATE RESOURCE GROUP high_priority
  TYPE = USER
  VCPU = (0,1)
  THREAD_PRIORITY = -10;

创建一个名为low_priority的资源组，使用 CPU 核心 2，线程优先级为 10。

CREATE RESOURCE GROUP low_priority
  TYPE = USER
  VCPU = (2)
  THREAD_PRIORITY = 10;

修改资源组：

修改资源组的语法如下：

ALTER RESOURCE GROUP group_name
  [VCPU = (cpu_list)]
  [THREAD_PRIORITY = priority]
  [RESOURCE_GROUP_ENABLE={TRUE|FALSE}];

举个栗子：

修改high_priority资源组的线程优先级为 -5。

ALTER RESOURCE GROUP high_priority
  THREAD_PRIORITY = -5;

删除资源组：

删除资源组的语法如下：

DROP RESOURCE GROUP group_name;

举个栗子：

删除low_priority资源组。

DROP RESOURCE GROUP low_priority;

第三部分：Resource Groups 的“十八般武艺”：使用方法

创建好资源组后，就可以把线程分配到不同的资源组了。

分配线程到资源组：

可以通过以下几种方式将线程分配到资源组：

在连接时指定： 在连接 MySQL 服务器时，可以使用--resource-group选项指定资源组。

mysql --user=your_user --password=your_password --resource-group=high_priority

在会话中指定： 在会话中，可以使用SET RESOURCE GROUP语句指定资源组。

SET RESOURCE GROUP high_priority;

使用 Performance Schema： 可以使用 Performance Schema 将线程分配到资源组。

举个栗子：

将当前会话分配到high_priority资源组。

SET RESOURCE GROUP high_priority;

-- 执行一些重要的查询
SELECT * FROM important_table WHERE ...;

-- 恢复到默认资源组
SET RESOURCE GROUP DEFAULT;

查看线程所属的资源组：

可以使用以下查询查看线程所属的资源组：

SELECT THREAD_ID, RESOURCE_GROUP FROM performance_schema.threads;

第四部分：Resource Groups 的“实战演练”：防止恶意查询

现在，咱们来模拟一个恶意查询，看看 Resource Groups 是如何发挥作用的。

场景：

一个“不懂事”的开发人员写了一个复杂的查询，导致 CPU 占用率飙升，影响了其他用户的正常使用。

SELECT
  t1.*
FROM
  table1 t1
JOIN
  table2 t2 ON t1.id = t2.table1_id
JOIN
  table3 t3 ON t2.id = t3.table2_id
JOIN
  table4 t4 ON t3.id = t4.table3_id
WHERE
  t1.column1 LIKE '%keyword%'
  AND t2.column2 > 100
  AND t3.column3 < 50
  AND t4.column4 = 'value';

这个查询涉及多个表的连接，并且使用了LIKE模糊查询，效率很低。

解决方案：

1. 创建一个低优先级资源组：

CREATE RESOURCE GROUP low_priority
  TYPE = USER
  VCPU = (2)
  THREAD_PRIORITY = 10;

2. 将执行恶意查询的线程分配到低优先级资源组：

可以通过多种方式进行分配，比如在连接时指定，或者使用 Performance Schema。这里假设我们已经知道执行恶意查询的线程 ID 是 123。

-- 使用 Performance Schema (需要一定的配置)
UPDATE performance_schema.threads
SET RESOURCE_GROUP = 'low_priority'
WHERE THREAD_ID = 123;

注意： 使用 Performance Schema 修改线程的资源组需要一定的权限和配置。更常用的方式是在连接时指定，或者在会话中指定。

3. 监控资源使用情况：

可以使用 MySQL Enterprise Monitor 或其他监控工具监控 CPU 和 IO 使用情况。

通过将执行恶意查询的线程分配到低优先级资源组，可以限制其 CPU 和 IO 使用，从而避免影响其他用户的正常使用。

第五部分：Resource Groups 的“进阶秘籍”：与其他功能的配合

Resource Groups 可以与其他 MySQL 功能配合使用，以实现更精细的资源管理。

Performance Schema： Performance Schema 提供了丰富的性能数据，可以用来监控资源组的使用情况，并根据实际情况调整资源组的配置。

用户权限管理： 可以结合用户权限管理，限制某些用户只能使用特定的资源组。

审计日志： 可以开启审计日志，记录资源组的使用情况，以便进行审计和分析。

第六部分：Resource Groups 的“注意事项”：坑爹的地方

资源组的配置需要根据实际情况进行调整。 没有万能的配置，需要根据服务器的硬件配置、负载情况等因素进行调整。

过度使用资源组可能会导致性能下降。 如果资源组的配置不合理，可能会导致线程之间的竞争，反而降低性能。

Resource Groups 不能完全解决所有资源管理问题。 仍然需要优化 SQL 查询，避免出现低效的查询。

第七部分：Resource Groups 的“未来展望”：它还能干啥？

Resource Groups 是一个非常有用的功能，可以帮助咱们更好地管理 MySQL 服务器的资源。未来，Resource Groups 可能会支持更多的资源类型，例如内存、网络带宽等，从而实现更全面的资源管理。

第八部分：总结陈词：告别“资源争夺战”

总而言之，MySQL 的 Resource Groups 就像一个“资源调度员”，它可以把 CPU 和 IO 资源分配给不同的查询，防止“恶意查询”霸占资源，保证关键查询的性能。虽然配置和使用 Resource Groups 需要一定的技巧，但只要掌握了基本原理，就能轻松应对各种“资源争夺战”，让你的 MySQL 服务器更加稳定、高效。

代码示例总结：

操作 | SQL 语句 | 说明
开启 Resource Groups | SET GLOBAL resource_group_enabled = ON; | 开启 Resource Groups 功能。

创建资源组

CREATE RESOURCE GROUP high_priority TYPE = USER VCPU = (0,1) THREAD_PRIORITY = -10;
CREATE RESOURCE GROUP low_priority TYPE = USER VCPU = (2) THREAD_PRIORITY = 10;

创建两个资源组，分别命名为 high_priority 和 low_priority，并设置 CPU 核心和线程优先级。

修改资源组 | ALTER RESOURCE GROUP high_priority THREAD_PRIORITY = -5; | 修改 high_priority 资源组的线程优先级。
删除资源组 | DROP RESOURCE GROUP low_priority; | 删除 low_priority 资源组。

会话分配资源组

SET RESOURCE GROUP high_priority;
SET RESOURCE GROUP DEFAULT;

将当前会话分配到 high_priority 资源组，然后恢复到默认资源组。

查看线程所属资源组 | SELECT THREAD_ID, RESOURCE_GROUP FROM performance_schema.threads; | 查看所有线程所属的资源组。
连接时分配资源组 | mysql --user=your_user --password=your_password --resource-group=high_priority | 在连接 MySQL 服务器时，指定资源组。
使用Performance Schema分配资源组 | UPDATE performance_schema.threads SET RESOURCE_GROUP = 'low_priority' WHERE THREAD_ID = 123; | 使用 Performance Schema 将线程分配到 low_priority 资源组。 需要权限和配置。

今天的讲座就到这里，谢谢大家！希望大家以后都能用好 Resource Groups，让你的数据库不再受“恶意查询”的困扰！