MySQL命令行导入卡死或报错ERROR 2006(HY000)时,应避免直接执行mysql -u user -p db_name import_err.log;真正难点在于SQL隐式依赖,如视图依赖函数、存储过程依赖临时表、分区表ENGINE=InnoDB与ROW_FORMAT兼容性问题。
MySQL 命令行导入卡死或报错 ERROR 2006 (HY000) 怎么办
直接用 mysql -u user -p db_name 导入几个 gb 的 sql 文件,大概率会失败——不是连接超时,就是客户端内存溢出,或者服务端中断连接。根本原因不是文件太大,而是 mysql 客户端默认把整个文件读进内存再发给服务端,中间没缓冲、没分片。
实操建议:
- 改用
mysql --max-allowed-packet=1G --net-buffer-length=1M -u user -p db_name,但仅缓解,不根治;--max-allowed-packet必须同时在服务端配置(my.cnf中的max_allowed_packet)才生效 - 禁用自动提交:
SET autocommit=0;+ 手动COMMIT;能减少事务日志压力,但需确保 SQL 文件本身不含BEGIN/COMMIT - 最稳妥的做法:别硬扛,先拆文件,再逐批导入
用 split 拆 SQL 文件要注意哪些边界问题
split 是 Linux/macOS 下最快捷的拆分工具,但它按字节或行数切,而 SQL 文件里一行可能跨多行(比如带换行的 INSERT ... VALUES (...)),直接按行切极易破坏语句结构。
实操建议:
- 优先用
split -t ';' -l 1000 huge.sql part_—— 以分号为记录分隔符,-t ';'指定分隔符,-l 1000表示每 1000 个分号切一块(注意:GNUsplit支持-t,macOS 默认split不支持,需用gsplit) - 拆完务必检查每份开头是否含
USE `db_name`;或SET NAMES utf8mb4;,缺失会导致导入时表找不到或乱码 - 避免拆出空文件或半截
INSERT:用tail -n 1 part_aa | grep -q ';$'验证末尾是否完整结束
Python 脚本拆分 SQL 更可控,但容易忽略事务和字符编码
写脚本能精准识别 CREATE TABLE、INSERT、注释、多行字符串等结构,但多数人写的“按分号切”脚本,会把带分号的字段值(如 INSERT INTO t VALUES ('a;b');)误判为语句结束。
实操建议:
- 不要自己解析 SQL,用现成库:推荐
sqlparse(pip install sqlparse),它能正确识别语句边界,即使有嵌套括号、引号、注释也不崩 - 关键逻辑是:用
sqlparse.split(sql_text)得到语句列表,再按数量或大小累积写入新文件,每份开头加SET autocommit=0;,结尾加COMMIT; - 读取时必须指定编码:
open('huge.sql', encoding='utf-8-sig'),否则 Windows 写出的 BOM 头会让sqlparse解析失败
导入批次后怎么确认没丢数据或重复执行
分批导入最怕的是:某批失败重试时,INSERT IGNORE 或 REPLACE INTO 没加,导致主键冲突;或者没关外键检查,INSERT 顺序错乱引发约束错误。
实操建议:
- 每批开头加:
SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;;结尾加:SET FOREIGN_KEY_CHECKS=1; SET UNIQUE_CHECKS=1; - 用
mysql -u user -p -e "SELECT COUNT(*) FROM table_name;" db_name对比源库(如果可查)或上一批导入后的行数,而不是依赖“没报错就成功” - 导入命令加
-v参数(mysql -v -u ...)能看到实际执行的语句,方便定位哪条卡住;加--force可跳过单条错误继续,但要配合日志重定向:2> import_err.log
真正麻烦的从来不是拆文件,而是 SQL 里藏着的隐式依赖:视图依赖函数、存储过程依赖临时表、分区表的 ENGINE=InnoDB 和 ROW_FORMAT 兼容性……这些不会在拆分时暴露,只会在导入中途突然报错。










