应使用 shell 重定向命令 mysql -u user -p db_name < file.sql 导入大 SQL 文件,而非 source 命令;需显式指定库名、设置 --max_allowed_packet 和超时参数,并优化 SQL 脚本格式与执行环境。

别用 source 导入 1G+ SQL 文件
直接在 MySQL 客户端里执行 source 命令导入 1G 以上文件,大概率会卡住、静默退出或报 ERROR 2013 (HY000): Lost connection to MySQL server during query。这不是网络问题,是客户端设计限制:source 会逐行读取、解析、拼接再发送,中间缓存膨胀,旧版本甚至把整个文件加载进内存。它不是为批量导入设计的 —— 就算你调高了 max_allowed_packet,也拦不住解析层本身的瓶颈。
真正该用的命令:mysql -u user -p db_name < file.sql
这条 shell 级重定向命令绕过客户端 SQL 解析,让服务端直接流式接收原始字节,内存占用低、无中间缓冲、稳定性强。必须注意:
-
db_name必须显式指定,否则遇到INSERT INTO table会立刻报ERROR 1046 (3D000): No database selected - 如果 SQL 文件开头含
CREATE DATABASE或USE,先手动建库并确认用户有权限,或拆成两步:mysql -u root -p < create_db.sql && mysql -u root -p target_db < data.sql - 想看进度?装
pv:pv /path/to/big.sql | mysql -u root -p target_db(pv不是 MySQL 自带,需apt install pv或brew install pv)
关键参数必须提前设,否则仍会中断
即使用了重定向,服务端仍可能因包大小或超时拒绝接收。这些参数只对当前连接生效,无需改配置文件、不用重启 MySQL:
- 加
--max_allowed_packet=1G防ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes - 加
--net_read_timeout=3600 --net_write_timeout=3600防连接被 wait_timeout 中断 - 完整命令示例:
mysql -u root -p --max_allowed_packet=1G --net_read_timeout=3600 --net_write_timeout=3600 target_db < /data/big.sql
注意:不要用 set global max_allowed_packet = ...,那会影响所有连接,且对已建立连接无效;也不要依赖 my.cnf 里设了就万事大吉 —— 客户端启动时未显式传参,仍可能沿用默认值(比如 4MB)。
脚本内容比命令更重要:避免单行单 INSERT、关外键、删索引
即使命令和参数都对了,脚本本身写法差,导入速度也会慢几倍。重点检查:
- 确认 INSERT 是多值格式:
INSERT INTO t VALUES (1,'a'),(2,'b'),(3,'c');,而不是每行一个INSERT INTO t VALUES (1,'a');—— 后者会让网络往返和解析开销翻 N 倍 - 脚本开头加:
SET FOREIGN_KEY_CHECKS = 0;;结尾加:SET FOREIGN_KEY_CHECKS = 1;,否则外键校验拖慢插入 - 如有大量数据,导入前手动
ALTER TABLE t DISABLE KEYS;,导入后再ENABLE KEYS;(仅 MyISAM 有效;InnoDB 推荐删非主键索引,导入完重建) - 避免脚本里混
SET autocommit = 0却没配COMMIT,会导致事务长期挂起、磁盘空间暴涨
最易被忽略的是:脚本里若有 DROP TABLE IF EXISTS 或 CREATE TABLE,但权限不足或表名冲突,错误发生后重定向模式不会报错退出,而是继续执行后续语句 —— 可能导致后面所有 INSERT 全丢进不存在的表,无声失败。


















