mysql 8.0资源组不能限制cpu使用率,仅支持vcpu亲和性绑定和thread_priority调度优先级控制;必须显式指定type=user与真实vcpu范围才生效,且仅对select查询有效,dml语句完全绕过。

资源组不能限制CPU使用率,只能做亲和性+优先级调度
MySQL 8.0 的 RESOURCE GROUP 不是 cgroups,它不控制“用了多少 CPU”,只决定“在哪跑、谁先跑”。你配完发现慢查询线程仍占满一个核,这完全正常——因为 MySQL 没有做时间片削峰或硬限频。真正起作用的是两件事:VCPU 绑定(把线程尽量钉在指定逻辑 CPU 上)和 THREAD_PRIORITY(影响内核调度顺序)。如果你指望靠它把某个 SQL 的 CPU 占用压到 30%,会彻底落空。
创建资源组必须显式指定 TYPE 和 VCPU 才生效
漏掉任一关键参数,CREATE RESOURCE GROUP 虽然执行成功,但实际无效。查 INFORMATION_SCHEMA.RESOURCE_GROUPS 会发现 VCPU_IDS 是 NULL 或 0-0,绑定后照样跑满所有核。
-
TYPE只能是USER(用户线程专用),SYSTEM类型仅限 MySQL 内部线程(如io_thread),普通用户无法绑定 -
VCPU必须填服务器真实存在的逻辑 CPU ID,比如 8 线程机器 ID 是 0–7,写VCPU = 4-7有效,写VCPU = "0-3"(带引号)或VCPU = 8-15会报错或失效 - 支持三种格式:
0(单核)、2-5(连续)、0,2,4(离散),不能混用,也不能留空 - 务必预留至少 1–2 个核给系统线程(如
SYS_default),否则mysqld自身可能卡死在 metadata lock 或 purge 上
SET RESOURCE GROUP FOR thread_id 只影响后续查询,不中断当前执行
这是最常被误用的点。执行 SET RESOURCE GROUP high_priority FOR 12345 后,线程 ID 12345 正在运行的那条事务语句(哪怕是个 5 分钟的 SELECT)不会暂停、不会迁移、也不会降优先级——它继续在原 CPU 上跑完。只有下一条语句才走新规则。
- 查线程 ID 必须用
performance_schema.threads.THREAD_ID(不是PROCESSLIST_ID),且确认performance_schema已启用(默认关闭) - 目标线程状态不能是
Sleep,否则报错ERROR 3661 (HY000);也不能处于Waiting for table metadata lock等不可中断状态 - 应用用了连接池时,
THREAD_ID复用频繁,刚绑完可能就被下一个请求覆盖,实际没生效 - 真想干预运行中查询,得先
KILL QUERY 12345,再让应用重试,并确保重试连接已绑定资源组(比如通过ALTER USER ... RESOURCE GROUP)
资源组只对 SELECT 生效,INSERT/UPDATE/DELETE 完全绕过
这是最容易被忽略的硬限制:RESOURCE GROUP 在 MySQL 8.0 中**仅对优化器选择的 SELECT 查询生效**。所有写操作(INSERT、UPDATE、DELETE、ALTER TABLE)完全绕过资源组调度逻辑。哪怕你把一个长事务里的 UPDATE 所在线程绑到低优先级组,它照样在所有 CPU 上自由调度,CPU 占用不受控。
- 如果你的核心事务含大量 DML(比如转账事务包含
UPDATE account SET balance = balance - 10000 WHERE id = 1),资源组对这部分毫无约束力 - 验证是否生效,只测
SELECT SLEEP(10)这类纯读语句,别拿UPDATE ... WHERE去试 - 写操作类负载主导的场景,应转向
MAX_UPDATES_PER_HOUR或外部cgroups,而不是依赖资源组
复杂点在于:资源组的隔离效果高度依赖操作系统调度行为,VCPU 绑定不是硬隔离——如果指定的核全忙而其他核空闲,内核仍可能把线程迁过去;THREAD_PRIORITY 在 Linux 上需 mysqld 进程提前授予 CAP_SYS_NICE 能力(setcap cap_sys_nice+ep /usr/sbin/mysqld),否则设了等于白设;而且优先级差异只有在多线程争抢同一组 VCPU 时才明显,若你给关键事务单独划出 0-1 核、给报表划出 2-3 核,优先级几乎不起作用。











