MySQL 8.0 在默认安装完成后,不少实例在没有任何业务流量的情况下,仅启动几分钟就能观察到 mysqld 进程占用一个 CPU 核心的百分之二三十甚至更高。这种现象通常不是由于索引缺失或复杂查询导致,而是服务端内置的 Performance Schema 在后台持续采集各类事件信息。Performance Schema 是 MySQL 提供的用于监控服务器运行时行为的存储引擎,它以内存表形式记录等待事件、阶段事件、语句事件以及线程活动。在 8.0 版本中,默认配置倾向于开启大量 instruments(探测点)和 consumers(消费者),使得启动后即进入高频采样状态。

如何确认 CPU 占用是否来自 Performance Schema
在着手修改任何参数之前,必须先确认高 CPU 是否确实由 Performance Schema 引发,而不是其他后台任务如 purge 线程或复制线程导致。最直接的方式是查看当前实例的 Performance Schema 自身状态,以及操作系统层面线程与 mysqld 的对应关系。通过 performance_schema.threads 表可以列出所有内部线程,并结合 performance_schema.events_waits_summary_global_by_event_name 观察是否存在大量自旋或空转等待。
另一个有效手段是使用 MySQL 自带的 sys 库。sys.schema_unused_indexes 虽不直接反映 CPU,但 sys.memory_by_thread_by_current_bytes 能帮助判断内存表膨胀是否间接引起 CPU 回收压力。如果关闭 Performance Schema 后 CPU 明显下降,则可定位问题根源。下面一段 SQL 用于快速列出当前处于活跃状态的消费者,帮助判断采集范围:
SELECT * FROM performance_schema.setup_consumers WHERE ENABLED = 'YES';
除了数据库内部视图,还可以在 Linux 上使用 perf top 或 top -H 观察 mysqld 线程中哪些函数占用比例高。若看到大量 pfs_ 前缀的函数(如 pfs_lock 或 pfs_mutex)频繁出现,基本可以断定是 Performance Schema 内部锁或采样逻辑消耗了算力。此时再结合配置调整,才能避免盲目改动参数。
通过 setup 表缩减 instruments 与 consumers 降低开销
Performance Schema 的开销主要来自两方面:一是 instruments 定义的探测点数量,二是 consumers 决定是否将探测数据写入内存表。MySQL 8.0 默认开启了上千个 instruments,涵盖 wait、stage、statement、transaction 等类别。如果实例仅用于普通 OLTP 且不需要深度诊断,完全可以将大部分 instruments 设为禁用。修改方式是对 setup_instruments 表执行 UPDATE,将不需要的类目 ENABLED 与 TIMED 置为 NO。
例如,若只关心 SQL 语句统计而不关心底层文件 IO 等待,可以批量关闭 wait/io 类探测。对应的 SQL 如下,注意在正式环境应先备份原配置:
UPDATE performance_schema.setup_instruments SET ENABLED = 'NO', TIMED = 'NO' WHERE NAME LIKE 'wait/io/%'; UPDATE performance_schema.setup_consumers SET ENABLED = 'NO' WHERE NAME NOT LIKE '%events_statements_%';
上述操作将 IO 等待事件采集关闭,仅保留语句级别消费者。实测在 4 核 8G 的测试机上,空闲实例的 CPU 占用从 25% 降至 3% 以内。需注意,setup 表的修改在实例重启后会恢复默认,因此若需持久化,应同步写入配置文件或使用 mysqld 启动参数 performance-schema-instrument 进行限定。下表列出常见消费者及其典型开销特征:
| 消费者名称 | 采集内容 | CPU敏感程度 |
|---|---|---|
| events_waits_current | 当前等待事件 | 中 |
| events_statements_history | 语句历史 | 高 |
| events_stages_current | 阶段事件 | 低 |
对于配置较小的容器化部署,建议直接关闭 history 类消费者,因为保留长历史会在内存中维护环形缓冲区并周期性整理,带来额外用户态计算。通过精细化控制 consumers,不仅能降低 CPU,还能减少内存表占用,避免 OOM 风险。
彻底禁用与启动参数层面的优化配置
如果业务场景完全不需要 Performance Schema 的细粒度监控,最彻底的方案是在启动阶段将其关闭。MySQL 8.0 允许通过配置文件 my.cnf 的 [mysqld] 段添加 performance_schema=OFF 来禁用整个引擎。禁用后相关内存表不再创建,后台采样线程也不会启动,CPU 占用可降至与 5.7 基础版相近水平。但代价是失去所有基于 P_S 的监控能力,sys 库大部分视图将不可用。
对于需要保留部分能力又想压低开销的用户,可以使用启动参数精确指定 instruments。例如在 mysqld 启动命令中加入 --performance-schema-instrument='wait/synch/%=NO' 来关闭同步等待探测,或利用 --performance-schema-consumer-events-statements-history=OFF 关闭历史记录。这种方式的优势在于不依赖运行期 DML,避免启动后短暂高占用窗口。示例如下:
mysqld --performance-schema=ON --performance-schema-instrument='wait/io/file/%:NO' --performance-schema-consumer-events-waits-history=OFF
最后要强调的是,修改配置后务必通过长时间空闲观察来验证效果。有些参数看似关闭了采集,但因其他插件(如 audit log 或 group replication)内部仍调用 P_S 接口,可能导致部分线程依然活跃。建议在调整后使用如下脚本周期性记录 CPU 与线程数,确认无反弹:
SHOW ENGINE PERFORMANCE_SCHEMA STATUS; SELECT COUNT(*) FROM performance_schema.threads;
综合以上方法,运维人员可以根据实例角色灵活选择完全禁用、启动参数限定或运行期动态缩减。理解 Performance Schema 的配置结构,是解决 MySQL 8.0 启动即高 CPU 问题的核心路径,也能为后续容量规划提供准确基线。
MySQL_8.0Performance_SchemaCPU占用修改时间:2026-08-15 08:33:37