mysql 8.0 还原大 sql 脚本慢的主因是默认启用的 performance_schema 采集、innodb_doublewrite 和过大的 innodb_redo_log_capacity,关闭或调优这三项可显著提速;此外删除非必要索引、禁用 extended-insert、合理设置 buffer_pool_size 等亦有效。

MySQL 8.0 还原大容量 SQL 脚本慢,核心问题不在“数据量大”本身,而在于默认开启的几项安全与监控机制,在纯读取场景下产生了大量无意义同步开销——关掉它们,速度常能回到 5.7 水平。
mysqldump 恢复时 performance_schema 拖慢整条链路
8.0 默认启用 events_statements_history_long 和 events_waits_history_long 等 consumer,每个 INSERT/SELECT 都触发采集逻辑。实测单表导入耗时增加 15%~40%,且无法通过 SET GLOBAL 关闭。
- 必须用
UPDATE performance_schema.setup_consumers SET ENABLED = 'NO' WHERE NAME LIKE 'events_statements_%' OR NAME LIKE 'events_waits_%'; - 执行后立即生效,无需重启;恢复完成后可再设回
'YES' - 注意:仅对当前连接生效,若用
mysql -e "source xxx.sql"方式导入,需在同一条连接里先执行该 UPDATE
innodb_doublewrite 在只读恢复中纯属冗余开销
逻辑还原(如 source 大 SQL 文件)不写数据页,但 innodb_doublewrite = ON 仍会强制校验 doublewrite buffer 元数据,尤其 buffer pool miss 高时,CPU 和内存访问压力明显上升。
- 导入前执行
SET GLOBAL innodb_doublewrite = OFF; - 导入完成立刻设回
ON,不影响数据一致性 - 该操作是临时的、安全的,不是永久禁用
innodb_redo_log_capacity 设置过大导致崩溃恢复卡顿(影响后续启动)
如果你的 SQL 脚本导入中途崩溃或被 kill,下次启动会进入 Starting crash recovery... 阶段。此时耗时 ≈ 待重放 Redo Log 总字节数 ÷ 磁盘顺序读速度。若 innodb_redo_log_capacity 设为 8GB,但实际写入峰值仅 10MB/s,5 分钟才写 3GB,却要扫描全部 8GB 找有效段落。
- 用
SELECT SUM(VARIABLE_VALUE) FROM performance_schema.global_status WHERE VARIABLE_NAME LIKE 'Innodb_os_log_written';每 30 秒查两次,差值除以 30 得出实时写入速率 - 按 RTO(如 300 秒)× 峰值速率算出合理值,例如 18MB/s →
SET GLOBAL innodb_redo_log_capacity = 5505024000 -
innodb_redo_log_capacity单位是字节,不是 MB;MySQL 8.0.30+ 已废弃innodb_log_file_size,配置里留它会直接报错
其他易被忽略的加速点
这些不改参数也能见效,但常被跳过:
- 导入前删掉目标表所有非必要索引,导入完成后再建——避免每行 INSERT 都触发索引维护
- 用
mysql --skip-extended-insert导入,减少客户端解析压力(尤其当 dump 含百万级单 INSERT) - 确保
innodb_buffer_pool_size足够大,让整个导入过程尽量走内存,而非频繁刷脏页 - 别用
--single-transaction+--lock-tables混用,8.0 下前者隐式启用READ COMMITTED,遇到长事务可能卡住 MVCC 版本链扫描
真正卡住还原的,往往不是磁盘或 CPU,而是你没关掉的那几个默认开关。调参前先确认是否真需要它们——逻辑还原不需要 doublewrite,也不需要 statement history,更不需要比实际写入多出一倍的日志容量。











