mysql导入备份时cpu打满主因是单线程sql解析与innodb索引维护等纯cpu操作,非io瓶颈;应限速输入流、关闭唯一性检查与自动提交、删除非必要索引,并优化dump文件结构。

导入时CPU打满,不是IO瓶颈而是解析/写入逻辑在狂转
MySQL导入备份(如 mysql 命令重放 SQL 文件)时 CPU 达 100%,通常不是磁盘或网络慢,而是单线程执行 SQL 的解析、权限校验、InnoDB 行格式转换、二级索引维护、唯一性检查等操作把单核吃满了。尤其当备份含大量 INSERT、UPDATE 或建表语句,且目标表已有索引时,每条语句都要触发索引 B+ 树分裂、页合并、MVCC 版本链维护——这些全是纯 CPU 密集型动作。
此时调大 innodb_buffer_pool_size 没用,因为数据还没刷进 Buffer Pool;关查询缓存(query_cache_type = 0)也无效,因导入过程根本不用缓存;盲目加 tmp_table_size 反而让临时排序更猛。
用 pv + mysql 管道限速,最轻量有效
不改 MySQL 配置、不中断导入、不依赖额外工具,仅靠 shell 管道就能控速。核心是把 SQL 流“掐住脖子”喂给 MySQL:
-
pv -L 500k backup.sql | mysql -u root -p db_name:限制输入流为 500KB/s,大幅降低单位时间解析语句数 - 若语句极短(如大批
INSERT INTO t VALUES (1),(2),...),可改用行数限速:awk 'NR%100==0{system("sleep 0.1")}1' backup.sql | mysql -u root -p db_name - 避免用
pv -L直接压.sql.gz,先解压再限速;否则 gzip 解压本身又占一核 CPU
导入前必须做的三件事,否则限速也白搭
限速只是缓解,不解决底层开销来源。以下操作必须在导入前执行,否则 CPU 仍会周期性冲高:
- 关闭唯一性检查:
SET UNIQUE_CHECKS=0;(导入后记得SET UNIQUE_CHECKS=1;) - 关闭自动提交:
SET AUTOCOMMIT=0;,并在每 1000–5000 行后显式COMMIT;,减少事务日志刷盘频率 - 删掉目标表所有非必要索引,导入完成后再重建;联合索引留一个覆盖主键的即可,其余全删
注意:FOREIGN_KEY_CHECKS=0 要谨慎,仅当确认外键约束无实际业务意义时才关——否则导入后数据一致性无法保障。
mysqldump 备份文件里藏着的坑
很多高 CPU 源自 dump 文件本身结构。打开备份文件看开头几行:
- 若有
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;这类兼容性设置,保留;但若含CREATE TABLE ... ENGINE=MyISAM却导入到 InnoDB 实例,会触发隐式引擎转换,CPU 飙升 - 检查是否含
DELIMITER+ 存储过程定义:这类语句解析开销极大,建议拆出单独导入,或用--skip-routines重 dump - 含大量
INSERT INTO t VALUES (...),(...),(...)是理想格式;若每行一个INSERT,导入速度慢 5–10 倍,CPU 利用率反而更高(解析开销占比上升)
真正难处理的是带触发器或事件调度器定义的 dump —— 它们会在导入时注册并可能立即触发,这种场景下限速无效,必须先 grep -n "CREATE TRIGGER\|CREATE EVENT" backup.sql 手动剥离。











