mysql 8.0资源组无法限制慢sql的cpu消耗量,仅控制“在哪跑、谁先跑”;必须指定type=user和真实vcpu才生效,否则vcpu_ids为null或0-0,且仅对select生效,dml完全绕过。

MySQL 8.0 的资源组无法限制慢 SQL 的 CPU 消耗量,只能控制它“在哪跑、谁先跑”——不降频率、不限核数、不中断执行。
CREATE RESOURCE GROUP 必须带 TYPE=USER 和真实 VCPU 才生效
漏掉 TYPE 或 VCPU,语句能执行成功,但资源组只是个空壳:查 INFORMATION_SCHEMA.RESOURCE_GROUPS 会发现 VCPU_IDS 是 NULL 或 0-0,绑给线程后毫无约束力。
-
TYPE = USER是强制项,用户线程不能用SYSTEM类型 -
VCPU必须填服务器真实逻辑 CPU ID,比如 8 核机器可用0、2-5、0,2,4;写VCPU = "0-3"(带引号)或VCPU = 8-15会静默失败或报错 - 务必预留至少 1–2 个核给
SYS_default,否则 purge 线程或 metadata lock 可能卡死 mysqld
SET RESOURCE GROUP FOR thread_id 只影响下一条语句
执行 SET RESOURCE GROUP slow_rg FOR 12345 后,线程 12345 正在运行的那条慢 SQL 不会暂停、迁移或降优先级——它继续在原 CPU 上跑完。只有下一条新发起的语句才走新资源组规则。
-
thread_id必须是performance_schema.threads.THREAD_ID,不是PROCESSLIST_ID - 目标线程状态不能是
Sleep,否则报错ERROR 3661 (HY000) - 若线程卡在
Waiting for table metadata lock等不可中断状态,SET会直接失败 - 想让限制“立即”生效,得先
KILL QUERY 12345,再让应用重连,并确保连接后立刻执行绑定
资源组只对 SELECT 生效,DML 完全绕过
这是硬限制,不是配置问题。哪怕你把一个正在执行 UPDATE 的线程显式绑到低优先级资源组,它仍会在所有 CPU 上自由调度,CPU 占用不受控。
- 验证是否生效,只能测纯读语句,例如
SELECT SLEEP(10)或复杂只读查询 -
INSERT/UPDATE/DELETE/ALTER TABLE这类写操作完全不走资源组调度逻辑 - 存储过程、触发器、事件中无法动态调用
SET RESOURCE GROUP - 如果负载以批量写入为主(如 ETL),资源组对这部分 CPU 占用毫无约束力
THREAD_PRIORITY 需配合 VCPU 绑定且依赖 OS 权限
THREAD_PRIORITY 映射到 Linux 的 nice 值(范围 0–19),但普通用户线程无法直接影响内核调度,除非 mysqld 进程被授予 CAP_SYS_NICE 能力。
- 执行
setcap cap_sys_nice+ep /usr/sbin/mysqld - 验证:
getcap /usr/sbin/mysqld应输出/usr/sbin/mysqld = cap_sys_nice+ep - 仅设
THREAD_PRIORITY而不配VCPU,效果极弱;两者必须同时生效才有实际调度差异 - 即使都配了,也只影响“谁先获得时间片”,不阻止单条 SELECT 跑满一个核
真正容易被忽略的是:资源组不解决“为什么慢”,只干预“怎么跑”。如果你的慢 SQL 是全表扫描或锁等待引发的连锁调度开销,资源组既不会加速它,也不会压低它的 CPU 使用率——它只是换个地方、换种顺序继续吃满 CPU。











