登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL RESOURCE GROUP 怎样为查询分配 CPU 资源

来源:17golang原创

时间:2026-10-16 22:41:11 369浏览 收藏

MySQL RESOURCE GROUP 适合处理“某类线程应该使用哪些 CPU、以什么优先级运行”的治理问题。它不是给单条 SQL 设定固定 CPU 配额,而是把服务器线程关联到资源组,再由资源组的 CPU 亲和性和线程优先级影响执行环境。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/resource-groups.html

最小可用路径是:确认平台和权限,创建一个启用的 USER 资源组;用 SET RESOURCE GROUP 绑定当前会话或线程,必要时用 RESOURCE_GROUP hint 只影响一条语句;最后从 INFORMATION_SCHEMA.RESOURCE_GROUPS 和 performance_schema.threads 读取归属。资源组管理只在当前服务器生效,不会通过复制自动传播。

先确认资源组能不能用

MySQL 8.4 把可管理的资源抽象为 virtual CPU,资源组可以设置非空 CPU 集合、线程优先级和启用状态。默认组 SYS_default 与 USR_default 不能删除或修改。资源组依赖平台能力:线程池插件启用时不可用,macOS 不提供 CPU 绑定所需的接口;Linux 上调整线程优先级还可能需要服务进程具备 CAP_SYS_NICE。

创建和修改资源组需要 RESOURCE_GROUP_ADMIN;管理线程归属通常需要 RESOURCE_GROUP_ADMIN 或 RESOURCE_GROUP_USER。先把这些前提写进运行手册,避免把“语句执行成功”误认为“CPU 治理已经生效”。

MySQL 资源组、CPU 亲和性、线程优先级与查询线程的静态关系说明图
图1:资源组定义说明图,查看资源组属性如何连接到 CPU 集合、优先级和查询线程;这是静态结构图,不是运行截图。

创建一个可回收的 USER 资源组

下面示例创建一个名为 report_low 的 USER 组,把它限制到虚拟 CPU 2 和 3,并使用较低的用户线程优先级。CPU 编号必须来自当前服务器可用的 virtual CPU;示例值用于说明语义,不能直接假定每台机器都有相同编号。

-- 创建一个可回收的用户组:只管理报表类线程,不改变默认组。
CREATE RESOURCE GROUP report_low
  TYPE = USER
  VCPU = 2, 3
  THREAD_PRIORITY = 10
  ENABLE;

-- 读取定义,确认名称、类型、启用状态和 CPU 集合。
SELECT RESOURCE_GROUP_NAME,
       RESOURCE_GROUP_TYPE,
       RESOURCE_GROUP_ENABLED,
       VCPU_IDS,
       THREAD_PRIORITY
FROM INFORMATION_SCHEMA.RESOURCE_GROUPS
WHERE RESOURCE_GROUP_NAME = 'report_low';

USER 组的线程优先级范围是 0 到 19,数值越大优先级越低;SYSTEM 组的范围是 -20 到 0。不要为了“提高报表优先级”把普通业务线程放到 SYSTEM 组,系统线程与用户线程的优先级边界本来就是隔离的。

把会话或单条语句绑定到资源组

如果一批报表查询共享一个会话,可以使用 SET RESOURCE GROUP 改变目标线程的资源组;如果只想影响一条语句,则使用优化器 hint,避免把同一连接后续的所有查询都带入低优先级组。

-- 当前会话切换到报表组;后续语句会沿用该线程归属。
SET RESOURCE GROUP report_low;

-- 只把这一条查询交给报表组,避免改变会话后续语句。
SELECT /*+ RESOURCE_GROUP(report_low) */
       department_id, COUNT(*) AS total
FROM report_events
GROUP BY department_id;

-- 查询结束后恢复默认用户组,释放临时治理边界。
SET RESOURCE GROUP USR_default;

会话绑定和语句 hint 是两个不同粒度:前者改变线程归属,后者只声明当前语句的资源组。若资源组被禁用,线程不能继续分配到该组;删除前也要先让线程回到默认组或其它仍启用的组。

MySQL SET RESOURCE GROUP、RESOURCE_GROUP hint、查询线程和默认用户组的静态关系说明图
图2:线程归属说明图,比较会话级绑定与单语句 hint 的范围,并标出恢复到 USR_default 的回收边界;这是静态结构图,不是运行截图。

从系统表读取归属并安排清理

INFORMATION_SCHEMA.RESOURCE_GROUPS 适合看资源组定义,performance_schema.threads 适合看服务器线程当前关联的资源组。两者分别回答“组怎么定义”和“线程现在归谁”,不要只看创建语句返回成功。

-- 查看资源组定义:确认治理参数仍符合运行手册。
SELECT *
FROM INFORMATION_SCHEMA.RESOURCE_GROUPS
WHERE RESOURCE_GROUP_NAME IN ('report_low', 'USR_default');

-- 查看线程归属:按当前连接的 THREAD_ID 对照资源组名称。
SELECT THREAD_ID, PROCESSLIST_ID, NAME, TYPE, RESOURCE_GROUP
FROM performance_schema.threads
WHERE RESOURCE_GROUP IN ('report_low', 'USR_default');

资源组定义保存在数据字典中,但资源组管理语句和修改不会写入 binary log,也不会复制到其它服务器。因此主从或集群环境要分别建立资源组,不要期待切换后远端节点自动拥有同名配置。

常见追问

资源组是不是 SQL 的固定 CPU 配额?

不是。它主要通过 CPU 亲和性和线程优先级治理线程执行条件,不等同于每条 SQL 的硬配额或准确的 CPU 百分比承诺。

为什么创建成功但优先级没有变化?

先看平台限制、服务进程权限和线程是否真的属于目标组。FreeBSD、Solaris 等平台可能忽略线程优先级;Linux 还可能需要 CAP_SYS_NICE。

实际落地时可以记住三件事:资源组先验证平台和权限,绑定时区分会话级与语句级,清理时把线程恢复到默认组。这样它才是可回收的查询治理边界,而不是一组只创建不观察的配置。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>