mysql 8.0 performance schema 默认开启且开销更大,新增大量 instrument 和 consumer(如 events_statements_%、events_transactions_%),导致高并发下 cpu 缓存压力上升、tps 下降 10%~30%;需关闭非必要 consumer 并按需启用细粒度监控(如 redo log 写入事件),同时调整 performance_schema_max_table_instances 等参数以避免内存瓶颈。

Performance Schema 默认开启且开销变大
MySQL 8.0 中 performance_schema 默认启用(5.7 也是,但 8.0 新增大量 instrument 和 consumer),且默认激活的采集项更多——尤其是 events_statements_% 和 events_transactions_%。这直接导致高并发 OLTP 场景下 CPU 缓存压力上升,实测 TPS 可能下降 10%~30%,尤其在 64+ 并发时明显。
常见错误现象:sysbench oltp_read_only 测试中 8.0 的平均 QPS 反而低于 5.7,top 显示 mysqld 占用 CPU 高但实际处理请求少。
- 必须在压测或生产前关闭非必要 consumer:
UPDATE performance_schema.setup_consumers SET ENABLED = 'NO' WHERE NAME LIKE 'events_statements_%'; - 若需保留语句级监控,至少禁用
events_statements_history_long(它默认保留 10000 条,内存占用高) - 5.7 的
setup_consumers表只有 12 行,8.0 达到 25+ 行,新增了events_stages%、events_waits%等细粒度开关
新增 wait/io/file/innodb/innodb_redo_log_write 等关键 instrument
8.0 新增了针对 InnoDB redo log 写入路径的精确等待事件,比如 wait/io/file/innodb/innodb_redo_log_write 和 wait/io/file/innodb/innodb_redo_log_flush。这些在 5.7 完全不可见,导致过去无法定位“小事务写 redo 慢”的根因。
使用场景:当 innodb_flush_log_at_trx_commit=1 下出现写延迟抖动,查 events_waits_summary_global_by_event_name 就能确认是否卡在 redo log fsync 或 CRC 校验环节。
- 注意:这些 instrument 默认是 DISABLED,需手动开启:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'wait/io/file/innodb/innodb_redo_log_write'; - 开启后会增加约 5%~8% 的额外 CPU 开销,仅在排查阶段启用
- 5.7 的
wait/io/file/innodb/下只有ib_log_file这一类粗粒度事件,无法区分 write/flush/fsync
memory/performance_schema/* 类内存监控更细粒度
8.0 把 Performance Schema 自身内存使用拆得更清:不再只有 memory/performance_schema 总览,而是按模块分出 memory/performance_schema/events_statements_history、memory/performance_schema/table_handles 等 30+ 项。这对诊断 “为什么 PS 占用几百 MB 内存” 很关键。
容易踩的坑:升级后未调大 performance_schema_max_table_instances(8.0 默认 50000,5.7 是 12800),遇到大量表或分区表时,table_handles 内存池耗尽会导致 SHOW PROCESSLIST 偶发卡顿或报错 ER_TABLE_NOT_FOUND。
- 检查当前用量:
SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED FROM performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE 'memory/performance_schema/%' ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 5; - 若
table_handles接近上限,需显式调大:SET GLOBAL performance_schema_max_table_instances = 100000; - 这个变量不能动态缩小,只能增大;且 8.0 启动时就按该值预分配内存,别设得过大浪费
setup_actors 表支持通配符过滤,但默认不生效
setup_actors 在 8.0 中支持 '%'、'localhost'、'10.%.%.%' 这类 host 匹配,可用于限制只监控特定应用用户的行为。但很多人忽略一点:即使插入了规则,consumers 里对应 events_statements% 必须为 YES,且 threads 表中该用户的 INSTRUMENTED 列必须是 YES,否则规则不触发。
典型误操作:往 setup_actors 插了一条 ('app_user', '%', 'YES'),结果发现该用户的语句依然没被采集。
- 确认是否生效:
SELECT * FROM performance_schema.threads WHERE USER = 'app_user'\G,看INSTRUMENTED是否为 YES - 若为 NO,执行:
UPDATE performance_schema.threads SET INSTRUMENTED = 'YES' WHERE TYPE = 'FOREGROUND' AND USER = 'app_user'; - 5.7 的
setup_actors表存在但完全不生效,字段也少(无 HOST 列),升级后需重置
真正影响排查效率的,不是多几个表或字段,而是 instrument 粒度和默认行为的变化——比如 redo log 写入路径拆分、内存按模块统计、actor 过滤需配合 threads 更新。这些细节不手动验证,很容易以为“开了 PS 就等于能看清瓶颈”。











