MySQL高级讲座篇之：如何利用MySQL的`Resource Groups`，进行`CPU`和`IO`的优先级调度？

admin
Sun, 17 Aug 2025 11:48:24 +0000
Mysql, groups, mysql, resource

大家好，欢迎来到今天的MySQL高级讲座！我是你们的老朋友，今天咱们聊点硬核的：MySQL的Resource Groups，以及如何用它来玩转CPU和IO的优先级调度。准备好了吗？咱们这就开始！ 开场白：资源争夺战与和平共处五项原则 想象一下，你的MySQL服务器就像一个拥挤的办公室，里面跑着各种各样的任务： 老板（重要查询）: “给我立刻查出昨天的销售额！” 小弟（后台任务）: “默默地做数据备份，不要打扰别人。” 实习生（临时报表）: “慢悠悠地跑着一个复杂的报表查询。” 如果大家一起争抢CPU和IO资源，结果可想而知：老板咆哮，小弟罢工，实习生崩溃。这时候，就需要一个“资源分配员”来维持秩序，确保重要任务优先完成，后台任务不影响前台，临时任务不会拖垮整个系统。 MySQL的Resource Groups就是这个“资源分配员”，它允许你将不同的线程分配到不同的组，并为每个组分配不同的CPU和IO优先级。这样，你就可以控制MySQL服务器的资源分配，优化性能，避免资源争夺。 第一部分：Resource Groups 基础入门 1.1 什么是 Resource Groups？ 简单来说 …

继续阅读“MySQL高级讲座篇之：如何利用MySQL的`Resource Groups`，进行`CPU`和`IO`的优先级调度？”

The post MySQL高级讲座篇之：如何利用MySQL的`Resource Groups`，进行`CPU`和`IO`的优先级调度？ first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

大家好，欢迎来到今天的MySQL高级讲座！我是你们的老朋友，今天咱们聊点硬核的：MySQL的Resource Groups，以及如何用它来玩转CPU和IO的优先级调度。准备好了吗？咱们这就开始！

开场白：资源争夺战与和平共处五项原则

想象一下，你的MySQL服务器就像一个拥挤的办公室，里面跑着各种各样的任务：

老板（重要查询）: “给我立刻查出昨天的销售额！”

小弟（后台任务）: “默默地做数据备份，不要打扰别人。”

实习生（临时报表）: “慢悠悠地跑着一个复杂的报表查询。”

如果大家一起争抢CPU和IO资源，结果可想而知：老板咆哮，小弟罢工，实习生崩溃。这时候，就需要一个“资源分配员”来维持秩序，确保重要任务优先完成，后台任务不影响前台，临时任务不会拖垮整个系统。

MySQL的Resource Groups就是这个“资源分配员”，它允许你将不同的线程分配到不同的组，并为每个组分配不同的CPU和IO优先级。这样，你就可以控制MySQL服务器的资源分配，优化性能，避免资源争夺。

第一部分：Resource Groups 基础入门

1.1 什么是 Resource Groups？

简单来说，Resource Groups是MySQL 8.0引入的一个功能，允许你：

创建资源组（Resource Group）: 定义一组资源限制（例如CPU亲和性，IO优先级）。

分配线程到资源组: 将MySQL线程（例如，执行查询的线程）分配到特定的资源组。

控制资源使用: MySQL根据资源组的设置来调度线程的资源使用。

1.2 Resource Groups 的类型

Resource Groups主要分为两种类型：

SYSTEM Resource Groups: 由MySQL服务器预定义，不能删除或修改。例如：

SYS_DEFAULT: 默认的资源组，所有未分配到其他组的线程都属于这个组。

SYS_BACKGROUND: 用于后台任务，例如日志刷新。

USER Resource Groups: 由用户创建和管理，可以自定义资源限制。

1.3 创建和管理 Resource Groups

咱们先来看看如何创建、修改和删除USER Resource Groups。

1.3.1 创建 Resource Group

使用CREATE RESOURCE GROUP语句创建资源组。

CREATE RESOURCE GROUP rg_important
  TYPE = USER
  VCPU = 2  -- 允许使用两个虚拟CPU
  IO_PRIORITY = 1; -- IO 优先级为1 (0为最高，7为最低)

解释一下：

rg_important: 资源组的名称。

TYPE = USER: 表明这是一个用户定义的资源组。

VCPU = 2: 指定该资源组可以使用的虚拟CPU数量。 这是一种CPU亲和性的设置，可以限定线程只能在特定的CPU核心上运行。

IO_PRIORITY = 1: 设置该资源组的IO优先级。

1.3.2 修改 Resource Group

使用ALTER RESOURCE GROUP语句修改资源组的属性。

ALTER RESOURCE GROUP rg_important
  VCPU = 4
  IO_PRIORITY = 0;

这个例子将 rg_important 资源组的VCPU数量增加到4，IO优先级设置为最高。

1.3.3 删除 Resource Group

使用DROP RESOURCE GROUP语句删除资源组。

DROP RESOURCE GROUP rg_important;

注意： 删除资源组前，必须确保没有线程分配到该资源组。

1.4 查看 Resource Groups 信息

使用SELECT语句从performance_schema.resource_groups表中查看资源组的信息。

SELECT * FROM performance_schema.resource_groups;

这个查询会显示所有资源组的名称、类型、VCPU设置和IO优先级等信息。

第二部分：CPU 优先级调度

2.1 CPU 亲和性（CPU Affinity）

CPU亲和性是指将进程或线程绑定到特定的CPU核心上运行。这可以提高性能，减少CPU切换的开销。

在Resource Groups中，可以使用VCPU属性来设置CPU亲和性。VCPU的值可以是：

DEFAULT: 使用服务器的默认设置。

n: 允许使用 n 个虚拟CPU。MySQL 8.0.14及更高版本，允许使用多个物理CPU核心来运行线程。

list of CPU IDs: 指定线程可以运行的CPU核心列表。

2.2 设置 CPU 亲和性示例

假设你的服务器有8个CPU核心，你想将rg_important资源组的线程绑定到CPU核心0和1上。

ALTER RESOURCE GROUP rg_important
  VCPU = (0,1);

注意：

CPU ID从0开始计数。

只有在服务器支持CPU亲和性时，这个设置才有效。

2.3 验证 CPU 亲和性

可以使用操作系统提供的工具来验证CPU亲和性是否生效。例如，在Linux上，可以使用taskset命令。首先，需要找到MySQL线程的ID。

1. 查找线程ID: 使用SHOW PROCESSLIST命令或者查询performance_schema.threads表找到你想要监控的线程ID.

SELECT THREAD_ID, NAME FROM performance_schema.threads WHERE NAME LIKE '%sql%';

2. 使用taskset命令: 假设线程ID是12345，可以使用以下命令查看该线程的CPU亲和性：

taskset -p 12345

如果CPU亲和性设置正确，taskset命令会显示线程绑定到CPU核心0和1上。

第三部分：IO 优先级调度

3.1 IO 优先级的重要性

IO优先级是指在进行磁盘读写操作时，不同线程之间的优先级。高优先级的线程可以更快地完成IO操作，而低优先级的线程则需要等待。

在Resource Groups中，可以使用IO_PRIORITY属性来设置IO优先级。IO_PRIORITY的值是一个整数，范围是0到7，其中0表示最高优先级，7表示最低优先级。

3.2 设置 IO 优先级示例

假设你想将rg_backup资源组的IO优先级设置为最低，以避免影响前台查询。

CREATE RESOURCE GROUP rg_backup
  TYPE = USER
  IO_PRIORITY = 7;

3.3 IO 优先级的实现机制

MySQL的IO优先级调度依赖于操作系统提供的IO调度器。不同的操作系统和IO调度器对IO优先级的支持程度可能不同。

Linux: Linux内核支持IO优先级调度，可以使用ionice命令来设置进程的IO优先级。MySQL的Resource Groups会通过ionice命令来设置线程的IO优先级。

Windows: Windows也支持IO优先级调度，但是MySQL对Windows的支持可能不如Linux完善。

3.4 验证 IO 优先级

在Linux上，可以使用ionice命令来验证IO优先级是否生效。

1. 查找线程ID: 同样，使用SHOW PROCESSLIST命令或者查询performance_schema.threads表找到你想要监控的线程ID。

2. 使用ionice命令: 假设线程ID是12345，可以使用以下命令查看该线程的IO优先级：

ionice -p 12345

如果IO优先级设置正确，ionice命令会显示线程的IO优先级为7 (idle)。

第四部分：将线程分配到 Resource Groups

4.1 分配线程的方式

有三种主要方式可以将线程分配到Resource Groups：

全局设置: 使用SET GLOBAL resource_group_name = 'group_name'; 设置全局默认的资源组。 新建立的连接默认使用这个资源组。

会话设置: 使用SET RESOURCE GROUP = 'group_name'; 将当前会话的所有线程分配到指定的资源组。

线程设置: 使用SET THREAD resource_group = 'group_name' FOR connection_id; 将指定的线程分配到指定的资源组。

4.2 分配线程示例

1. 全局设置:

SET GLOBAL resource_group_name = 'rg_important';

这个设置会将所有新建立的连接分配到rg_important资源组。 注意： 这个设置会影响所有的新连接，慎用！

2. 会话设置:

SET RESOURCE GROUP = 'rg_backup';

-- 在这个会话中执行的所有查询都将在 rg_backup 资源组中运行
SELECT * FROM large_table;

这个设置会将当前会话的所有线程分配到rg_backup资源组。

3. 线程设置:

-- 找到连接ID
SHOW PROCESSLIST;

-- 假设连接ID是 42
SET THREAD resource_group = 'rg_important' FOR 42;

这个设置会将连接ID为42的线程分配到rg_important资源组。

4.3 查看线程所属的 Resource Group

可以使用performance_schema.threads表查看线程所属的资源组。

SELECT THREAD_ID, NAME, RESOURCE_GROUP FROM performance_schema.threads;

这个查询会显示所有线程的ID、名称和所属的资源组。

第五部分：实战演练：优化查询性能

咱们来一个实战案例，假设你的MySQL服务器同时运行着在线交易和数据分析任务。在线交易需要快速响应，而数据分析任务可以容忍一定的延迟。

5.1 创建 Resource Groups

CREATE RESOURCE GROUP rg_online
  TYPE = USER
  VCPU = (0,1,2,3) -- 绑定到CPU核心 0-3
  IO_PRIORITY = 0;

CREATE RESOURCE GROUP rg_analysis
  TYPE = USER
  VCPU = (4,5,6,7) -- 绑定到CPU核心 4-7
  IO_PRIORITY = 7;

5.2 分配线程

将在线交易相关的连接分配到rg_online资源组。

将数据分析相关的连接分配到rg_analysis资源组。

5.3 测试效果

分别在rg_online和rg_analysis资源组中执行查询，观察查询的响应时间和CPU、IO的使用情况。

预期结果：

rg_online资源组的查询响应时间更快，CPU和IO使用率更高。

rg_analysis资源组的查询响应时间较慢，CPU和IO使用率较低。

第六部分：Resource Groups 的注意事项和最佳实践

监控: 密切监控Resource Groups的资源使用情况，及时调整配置。 使用 performance_schema 中的相关表。

测试: 在生产环境中使用Resource Groups之前，一定要进行充分的测试。

合理分配: 根据实际业务需求，合理分配CPU和IO资源。 不要过度限制某些资源组，导致任务无法完成。

版本兼容性: Resource Groups是MySQL 8.0引入的功能，低版本不支持。

操作系统支持: 确保你的操作系统支持IO优先级调度和CPU亲和性。

动态调整: 考虑使用存储过程或事件调度器来动态调整Resource Groups的配置，以适应不同的负载情况。

小心全局设置: SET GLOBAL resource_group_name 的影响范围很大，要谨慎使用。

总结：

今天咱们一起学习了MySQL的Resource Groups，以及如何使用它来进行CPU和IO的优先级调度。希望通过今天的讲座，你能够掌握Resource Groups的基本概念、用法和最佳实践，并在实际工作中灵活运用，优化MySQL服务器的性能。记住，合理分配资源，才能让你的MySQL服务器更加高效稳定！

今天的讲座就到这里，谢谢大家！ 下次再见！