迁移后新库CPU飙到100%主因是查询行为与新环境不匹配:统计信息未更新、索引失效、字符集/collation变更致隐式转换、tmp_table_size不足或thread_cache_size过小,应优先通过EXPLAIN和PROCESSLIST定位根因。
迁移后新库CPU飙到100%,大概率不是硬件或配置问题,而是查询行为与新环境不匹配——最常见的是统计信息未更新、索引失效、字符集/排序规则变更导致隐式转换,或执行计划彻底走偏。别急着调参或杀连接,先盯住 EXPLAIN 输出和 information_schema.PROCESSLIST 中的 State 值。
为什么迁移后执行计划突然变差?
MySQL优化器严重依赖表的统计信息做成本估算,而 mysqldump 或物理拷贝不会自动触发 ANALYZE TABLE。新库中 INFORMATION_SCHEMA.STATISTICS 里的行数、基数(cardinality)仍是空或过期值,导致优化器误判“全表扫描比走索引快”,尤其在 WHERE 条件字段有索引但基数不准时。
- 执行
SELECT table_name, table_rows, avg_row_length FROM information_schema.TABLES WHERE table_schema = 'your_db',对比迁移前后table_rows是否为 0 或明显失真 - 对高频表立刻执行
ANALYZE TABLE t1, t2, t3(注意:该操作会加 MDL 读锁,避开业务高峰) - 若用的是 MySQL 8.0+,确认
innodb_stats_auto_recalc是否为ON;若为OFF,需手动触发或设为ON
字符集或 collation 变更引发隐式转换
迁移时若把旧库的 utf8mb4_unicode_ci 改成 utf8mb4_0900_as_cs,或列级 collation 不一致,会导致 WHERE 或 JOIN 条件无法使用索引——EXPLAIN 中 type 显示 ALL,key 为 NULL,但 Extra 里没写 “Using index”,八成是这个原因。
- 查关键字段的 collation:
SHOW CREATE TABLE orders\G,重点看user_id、status等查询条件列 - 对比新旧库中相同查询的
EXPLAIN FORMAT=TRADITIONAL输出,关注possible_keys和key是否一致 - 临时修复:在 WHERE 子句中显式加
COLLATE,例如WHERE name COLLATE utf8mb4_unicode_ci = '张三';长期方案是统一列 collation
tmp_table_size 不足导致频繁落盘排序
迁移后若应用侧并发查询增多(比如新前端批量拉取),或排序字段没索引,MySQL 会在内存中建临时表做 ORDER BY / GROUP BY。一旦超出 tmp_table_size 或 max_heap_table_size,就会转成磁盘临时表,触发大量 CPU 计算和 IO,SHOW PROCESSLIST 中 State 显示 Creating sort index 或 Copying to tmp table 就是明证。
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
- 查当前设置:
SELECT @@tmp_table_size, @@max_heap_table_size(单位字节) - 紧急提升(无需重启):
SET GLOBAL tmp_table_size = 536870912;(512MB),同时设max_heap_table_size相同值 - 观察
SHOW GLOBAL STATUS LIKE 'Created_tmp%',若Created_tmp_disk_tables比Created_tmp_tables高出 20% 以上,说明落盘太频繁
连接数暴增 + thread_cache_size 过小引发上下文切换风暴
有些 ORM(如 Django 的 CONN_MAX_AGE=0)或连接池(HikariCP 默认 maximumPoolSize=10)在迁移后因 DNS 解析延迟、网络抖动或重连逻辑变化,导致短连接激增。这时 vmstat 1 里 cs(context switch)常超 15k/s,%sy(系统态 CPU)飙升,但 %us(用户态)反而不高——CPU 全花在调度线程上了,不是在执行 SQL。
- 查当前连接:
SHOW STATUS LIKE 'Threads_connected',对比迁移前峰值 - 查线程缓存命中率:
SHOW STATUS LIKE 'Threads_created'÷SHOW STATUS LIKE 'Connections',若 > 0.1,说明缓存严重不足 - 立即生效:
SET GLOBAL thread_cache_size = 16(建议设为 CPU 核数 × 2,但不超过 32) - 根本解法:应用层启用长连接,或调大连接池 idle timeout
真正卡点不在命令会不会敲,而在你是否敢在 PROCESSLIST 里看到 Sorting result 时,立刻去查那个 SQL 的 ORDER BY 字段有没有索引——而不是先去翻配置文件。