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

MySQL 资源组怎么限制批处理线程的 CPU

来源:17golang原创

时间:2026-09-28 00:36:53 303浏览 收藏

我在给夜间归档任务做 CPU 隔离时,发现 MySQL 资源组最容易被误解的地方是“限制”二字:它不是把批处理固定成 20% CPU,而是把线程放进指定的虚拟 CPU 集合,并可配合线程优先级影响调度。对批处理来说,常用方案是建立一个用户资源组,绑定少量 VCPU,再用会话级或单语句方式指派任务。

核心结论:先用 VCPU 缩小批处理可使用的 CPU 集合,再用 THREAD_PRIORITY 做相对优先级控制;如果需要严格的百分比配额,还要在 MySQL 之外配合操作系统或容器的 CPU 控制。

落地要点
  • 资源组创建和属性修改需要 RESOURCE_GROUP_ADMIN。
  • SET RESOURCE GROUP 适合整个批处理会话,RESOURCE_GROUP hint 适合单条 SQL。
  • 先查资源组和线程状态,再按高峰、低峰调整,不要只看 SQL 返回成功。

一、先分清 CPU 亲和性和 CPU 百分比限流

MySQL 批处理线程、资源组和 VCPU 亲和性的静态结构图
图1:批处理线程、Batch 资源组与 VCPU 集合的静态关系。

MySQL 把 CPU 核、超线程等抽象成 virtual CPU。资源组的 VCPU 属性表示线程可以在哪些虚拟 CPU 上运行;不设置亲和性时可以使用全部可用 CPU。THREAD_PRIORITY 是调度优先级,用户组可设置 0 到 19,数值越大优先级越低。

因此,VCPU = 2-3 更像“把批处理放到 CPU 2 和 3 的小房间”,不是“只允许它消耗整机 50%”。如果任务在这两个 CPU 上仍然持续繁忙,它依然可能占满这两个 CPU。

二、创建一个面向批处理的用户资源组

下面的示例假设服务器至少有 4 个虚拟 CPU,并让批处理优先级低于普通前台请求。资源组名称是标识符,创建后可以调整 VCPU 和优先级,但不能改变名称和类型。

-- 创建用户资源组,把批处理放到 VCPU 2 和 3
CREATE RESOURCE GROUP Batch
  TYPE = USER
  VCPU = 2-3
  THREAD_PRIORITY = 10;

-- 查看资源组是否已启用、绑定了哪些 VCPU
SELECT RESOURCE_GROUP_NAME,
       RESOURCE_GROUP_TYPE,
       RESOURCE_GROUP_ENABLED,
       VCPU_IDS,
       THREAD_PRIORITY
FROM INFORMATION_SCHEMA.RESOURCE_GROUPS
WHERE RESOURCE_GROUP_NAME = 'Batch';

创建、修改和删除资源组需要 RESOURCE_GROUP_ADMIN。如果只是把自己的线程指派到已有资源组,可以使用 RESOURCE_GROUP_USER;在自动化账号上,建议把权限边界和批处理账号分开记录。

三、把批处理会话或单条 SQL 指派进去

MySQL 资源组会话指派和单语句 hint 的边界图
图2:会话级指派与单语句 hint 的边界,以及平台能力限制。

如果一个连接接下来大部分时间都在跑导入、归档或报表,使用会话级指派更直观:

-- 只影响当前会话后续执行的语句
SET RESOURCE GROUP Batch;

-- 批处理完成后切回默认用户资源组
SET RESOURCE GROUP USR_default;

如果连接还要承担普通查询,不希望改变整个会话,可以只给某一条语句加 hint:

-- 只把这条归档语句放入 Batch 资源组
INSERT /*+ RESOURCE_GROUP(Batch) */ INTO archive_orders
SELECT * FROM orders
WHERE created_at 

两者的选择取决于任务边界:批处理连接独立时优先会话级指派;混合连接或只想控制一条重 SQL 时使用 hint。资源组必须已启用,否则线程不能被指派。

四、核对生效状态并按负载调整

我通常先看定义,再看线程归属。定义能确认 VCPU 和优先级,线程表能确认当前连接是否真的离开了默认组:

-- 检查资源组定义
SELECT RESOURCE_GROUP_NAME, RESOURCE_GROUP_ENABLED, VCPU_IDS, THREAD_PRIORITY
FROM INFORMATION_SCHEMA.RESOURCE_GROUPS;

-- 找出当前线程的资源组归属,便于和批处理连接对应
SELECT THREAD_ID, PROCESSLIST_ID, NAME, TYPE, RESOURCE_GROUP
FROM performance_schema.threads
WHERE PROCESSLIST_USER = 'batch_user';

白天高峰可以减少 Batch 的 VCPU 并降低优先级;夜间再扩大集合或恢复优先级。修改前先确认批处理是否可延迟,避免为了保护前台请求而把归档窗口推到业务高峰。

-- 高峰期只保留一个 VCPU,并把用户组优先级调低
ALTER RESOURCE GROUP Batch
  VCPU = 3
  THREAD_PRIORITY = 19;

-- 低峰期恢复到两个 VCPU 和默认优先级
ALTER RESOURCE GROUP Batch
  VCPU = 2-3
  THREAD_PRIORITY = 0;

五、处理平台限制和回退方案

资源组能否完整发挥作用取决于部署环境。MySQL 官方文档明确说明:安装了 thread pool plugin 时资源组不可用,macOS 没有 CPU 绑定所需接口;FreeBSD 和 Solaris 会忽略线程优先级。Linux 上优先级通常需要给 mysqld 进程授予 CAP_SYS_NICE,否则可能看到语句执行成功,但优先级仍是默认值。

# systemd 环境通过服务覆盖文件授予调度优先级能力
[Service]
# 只授予 CAP_SYS_NICE,不修改 mysqld 二进制文件
AmbientCapabilities=CAP_SYS_NICE

这项能力涉及进程调度权限,应该由运维按主机基线评估;如果不能启用,就把文章中的目标收窄为 VCPU 亲和性,并用操作系统或容器层的 CPU 配额完成百分比限制。不要把“Query OK”当作所有属性都已经生效的证据,还要复查资源组行、线程归属以及系统日志中的 warning。

怎么选资源组、会话指派和单语句 hint

场景推荐方式主要边界
独立批处理连接SET RESOURCE GROUP Batch影响当前会话后续语句
混合连接中的一条重 SQLRESOURCE_GROUP(Batch)只控制带 hint 的语句
需要硬 CPU 百分比配额配合操作系统或容器MySQL 资源组本身不是百分比限流器

相关问题

MySQL 资源组能不能限制到 30% CPU?

不能直接按百分比配置。它通过 VCPU 集合和线程优先级影响运行范围与调度,硬配额应交给操作系统或容器。

为什么设置 THREAD_PRIORITY 后仍然是 0?

先查平台限制,Linux 重点确认 CAP_SYS_NICE;FreeBSD 和 Solaris 的优先级本来就会被忽略。

资源组配置会复制到从库吗?

不会。资源组管理在执行它的服务器本地生效,相关 SQL 和数据字典修改不写入 binary log。

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