恢复慢的根本原因是SQL回放机制,而非mysqldump本身;需调大innodb_buffer_pool_size、max_allowed_packet、innodb_log_file_size等参数,关闭unique_checks和foreign_key_checks,并分批COMMIT以提升速度。

恢复慢的根本原因不是 mysqldump 本身,而是 SQL 回放机制
mysqldump 输出的是纯文本 SQL(CREATE TABLE + INSERT),恢复时 MySQL 必须逐条解析、校验、写入、刷日志、更新索引——这和直接拷贝数据文件的物理恢复有数量级差异。哪怕只是 10GB 的 dump 文件,实际执行的 INSERT 可能超千万条,每条都走完整事务路径。这不是“慢”,是设计使然。
关键参数必须在恢复前调大,否则默认值会拖垮速度
MySQL 默认配置专为稳定运行设计,不是为批量导入优化。不改就硬导,innodb_buffer_pool_size 小、max_allowed_packet 小、innodb_log_file_size 小,都会导致频繁刷盘、分包重试、日志切片,恢复时间翻倍甚至更糟。
-
innodb_buffer_pool_size至少设为物理内存的 50%~70%,确保大部分表数据和索引能常驻内存 -
max_allowed_packet必须 ≥ dump 文件中最大单条 INSERT(常见于含大 TEXT/BLOB 的表),建议从 256M 起调 -
innodb_log_file_size建议 ≥ 1G(需停库修改,且要先删旧日志文件再重启) - 临时关闭唯一性检查:
SET unique_checks=0;和SET foreign_key_checks=0;,恢复完再开
恢复时禁用索引比“先建表再插数据”更有效
很多人以为只要用 mysqldump --no-create-info 分开导出结构和数据就能提速,其实没用——真正卡点是索引维护。InnoDB 在每条 INSERT 后都要更新所有二级索引,IO 压力爆炸。
- 正确做法:导出时加
--skip-extended-insert(可选,便于调试),但恢复前手动在 SQL 文件头部插入:SET autocommit=0;和SET unique_checks=0; SET foreign_key_checks=0; - 更彻底的:用
sed -i 's/CREATE TABLE/CREATE TABLE ENGINE=InnoDB ROW_FORMAT=DYNAMIC;/g' backup.sql确保建表语句不含冗余选项 - 终极提速:把
INSERT块拆成 10k~50k 行一批,每批后跟COMMIT;,避免长事务撑爆 undo log
别忽略字符集和 SQL 模式兼容性问题
恢复中途报错退出,比慢更致命。常见于跨版本迁移(如 MySQL 5.7 → 8.0)或 dump 时未显式指定字符集。
- 导出时务必加:
--default-character-set=utf8mb4,否则可能默认用 latin1,恢复时报Incorrect string value - 恢复前执行:
SET sql_mode='STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';,匹配源库模式 - 如果 dump 文件里有
CREATE FUNCTION或DEFINER,需提前用sed -i 's/DEFINER=`[^`]*`@`[^`]*`//g' backup.sql清理,否则可能因用户不存在失败


















