mysql大文件导入应使用shell重定向而非source命令,因source逐行解析导致内存高、无并发、易中断;正确方式是mysql -u root -p --max_allowed_packet=1g target_db
mysql命令重定向导入比source快得多,且稳定;用错方式(比如在 MySQL 客户端里执行source)是慢的根本原因,不是配置或硬件问题。别用
source导入大文件source是客户端逐行读取、解析、拼接再发送的机制,内存占用高、无并发、无法中断恢复。1GB 以上文件大概率卡死或报ERROR 2013 (HY000): Lost connection to MySQL server during query或ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes。它不是为批量导入设计的。
- 真正该用的命令是 shell 级重定向:
mysql -u root -p --max_allowed_packet=1G target_db- 必须显式指定库名
target_db,否则遇到INSERT INTO table就报ERROR 1046 (3D000): No database selected- 如果 SQL 文件含
CREATE DATABASE或USE,先手动建库并授权,或拆成两步:mysql -u root -p关键参数必须每次导入都显式传
服务端参数只对当前连接生效,不传就用默认值(比如max_allowed_packet=4M),哪怕my.cnf里设了也没用。
- 加
--max_allowed_packet=1G防包截断- 加
--net_read_timeout=3600 --net_write_timeout=3600防因 wait_timeout 中断- 不要用
SET GLOBAL动态改,那会影响其他连接,且对已建立连接无效SQL 文件本身要“能跑快”
命令和参数都对了,脚本写法差照样慢几倍。
- 确保
INSERT是多值格式:INSERT INTO t VALUES (1,'a'),(2,'b'),(3,'c');,而不是每行一个INSERT- 导入前手动删掉开头的
SET NAMES utf8mb4类语句——它们在非交互式导入中常失效,改用连接参数--default-character-set=utf8mb4- 若文件含
CREATE TABLE,确保显式写ENGINE=InnoDB,避免低版本默认用 MyISAM 导致锁表- 在文件开头加
SET unique_checks=0; SET foreign_key_checks=0; SET autocommit=0;,结尾补COMMIT; SET unique_checks=1; SET foreign_key_checks=1;(前提是确认数据无主键/唯一键冲突)分卷比硬扛更实际
2GB 文件出错就得重来;拆成 50MB/份后,失败只需重试其中一份。但不能用split -l硬切——它不管语句边界,极易切坏INSERT。
- 更稳妥的方式是按
INSERT块切:awk '/^INSERT INTO/{n++} {print > "chunk_" int((n-1)/100) ".sql"}' large.sql(每 100 个INSERT分一份)- 想看进度?装
pv:pv /path/to/big.sql | mysql -u root -p target_db(apt install pv或brew install pv)真正卡住的地方,往往不是“没调参”,而是用了
source这个错误入口,或者 SQL 文件里还混着几十万行单条INSERT。优化得从命令和脚本结构开始,不是最后才想的事。












