source命令不支持超大文件高效导入,因其逐行解析、内存占用高、无服务端优化,易因max_allowed_packet过小(默认4MB)或DELIMITER语法错位导致卡死、ERROR 2006或Unknown command等错误。

source 命令本身不支持超大文件直接高效导入;百兆级 .sql 文件用它执行,极大概率卡死、超时或报错,必须提前做三件事:改客户端配置、确认编码、拆分或跳过非关键语句。
为什么 source /path/to/big.sql 会卡住甚至无响应?
MySQL 客户端默认的 max_allowed_packet 通常只有 4MB,而百兆 SQL 文件里单条 INSERT 可能就含几万行数据(尤其 mysqldump 加了 --extended-insert),一读就触发截断或连接中断。另外,source 是逐行解析执行的,不走服务端优化路径,没有事务批处理机制,遇到 DELIMITER 切换或存储过程定义时容易语法错位。
常见错误现象包括:
ERROR 2006 (HY000): MySQL server has gone away- 命令行长时间停在
mysql>提示符下不动,CPU 占用低但无输出 - 导入中途报
Unknown command '或Unexpected character
执行前必须调大的两个客户端参数
在启动 mysql 客户端时,不能只写 mysql -u root -p,要显式加大缓冲和超时:
- 加
--max-allowed-packet=512M:确保能吞下单条巨长 INSERT(注意单位是 M,不是 MB) - 加
--net-read-timeout=7200和--net-write-timeout=7200:防止网络层因长时间无响应断连(尤其远程服务器) - 可选加
--default-character-set=utf8mb4:避免源文件含 emoji 或四字节字符时报Incorrect string value
完整登录命令示例:
mysql -u root -p --max-allowed-packet=512M --net-read-timeout=7200 --net-write-timeout=7200 --default-character-set=utf8mb4
导入时如何绕过 CREATE DATABASE 和 USE 语句?
如果备份文件是用 mysqldump -B 生成的,开头有 CREATE DATABASE `xxx` 和 USE `xxx`,而目标库已存在或名字不同,source 会直接报错 Can't create database 'xxx'; database exists 或切换失败。
解决方法不是手动删文件(易出错),而是用 sed 或 awk 预处理:
- 跳过建库语句:
sed '/^CREATE DATABASE/d' backup.sql > clean.sql - 跳过 USE 语句:
sed '/^USE `/d' clean.sql > final.sql - 若需指定目标库,先在 mysql 中执行
USE target_db;,再source final.sql
注意:不要用 grep -v,它会误删表内含 USE 字样的注释或字段值。
比 source 更稳的替代方案:mysql 命令直导
对百兆文件,source 是“交互式模拟执行”,而 mysql 命令行工具是“流式管道导入”,底层走的是更精简的协议,几乎不占客户端内存,也自动处理分包。
推荐用法(前提:备份文件含建库语句,即用了 -B):
mysql -u root -p --max-allowed-packet=512M < backup.sql
若不含建库语句,必须先手动创建库并指定:
mysql -u root -p --max-allowed-packet=512M target_db < backup.sql
这个方式不进 mysql shell,没提示、没回显,但进度可用 pv 监控:
pv backup.sql | mysql -u root -p --max-allowed-packet=512M target_db
真正麻烦的从来不是命令怎么敲,而是备份文件里混着 SET FOREIGN_KEY_CHECKS=0 之后没恢复、或含 /*!50003 ... */ 这类条件注释却运行在低版本 MySQL 上——这些细节不会报错,但会导致外键失效或存储过程丢失,得靠人工扫一眼头尾几十行。


















