应分批导出大字段表:用--skip-extended-insert、--where分段、--max-allowed-packet调小;优先选SELECT...INTO OUTFILE(需满足secure_file_priv且服务端路径可写);导入时同步调大服务端与客户端max_allowed_packet并指定utf8mb4字符集;应用层需字段精简、游标分页、流式读取。

大字段导致 mysqldump 卡死或超时怎么办
直接用默认参数导出含 LONGTEXT 或 LONGBLOB 的表,mysqldump 常在读取阶段卡住、报 MySQL server has gone away,本质是单次查询拉回太多数据,触发了服务端 max_allowed_packet 或客户端网络超时。
关键不是“加大超时”,而是让每次传输量可控:
- 加
--skip-extended-insert:避免单条INSERT包含上百行,降低单语句长度和内存压力 - 强制分批导出:用
--where="id BETWEEN 1 AND 10000"配合循环,比依赖--limit更可靠(后者在有大字段时仍可能超载) - 调低客户端包大小:启动
mysqldump时加--max-allowed-packet=32M,必须 ≤ 服务端同名参数值,否则无效
用 SELECT ... INTO OUTFILE 导出大字段更稳但有前提
这个方式绕过客户端缓冲,由 MySQL 服务端直写文件,对大字段更友好,但有两个硬限制:
- 目标路径必须是 MySQL 服务进程有写权限的**本地路径**(不是你本机),常见错误是填了
/tmp/export.csv却忘了它实际在数据库服务器上 - 必须开启
secure_file_priv,且路径需落在该配置指定目录下;查当前值:执行SHOW VARIABLES LIKE 'secure_file_priv' - 不能直接导出多表或带 JOIN,适合单表批量导出;字段含换行符时,要用
FIELDS ENCLOSED BY '"'包裹,否则后续导入会错位
迁移中 LOAD DATA INFILE 导入失败的典型原因
即使导出成功,导入时仍容易因大字段报错,比如 Packet too large 或 Incorrect string value:
- 服务端
max_allowed_packet必须 ≥ 导入单行最大长度(尤其含 Base64 编码的LONGBLOB),建议设为 512M 并重启 mysqld - 客户端也要同步调大:连接时加
--max-allowed-packet=512M,否则 MySQL 客户端库会截断 - 字符集不一致会导致
Incorrect string value,确保导出文件保存为utf8mb4编码,并在LOAD DATA语句里显式写CHARACTER SET utf8mb4
应用层分批同步时,SELECT 大字段的性能陷阱
如果用程序(如 Python/Go)读取再写入新库,别用 SELECT * 直接捞整张表——大字段会把内存和网络拖垮:
- 只查必要字段:
SELECT id, title, content比SELECT *少传几个 MB,延迟下降明显 - 用游标分页而非
OFFSET:大表 + 大字段下,LIMIT 100000, 1000会扫描 10 万行再丢弃,改用WHERE id > 100000 ORDER BY id LIMIT 1000 - 结果集获取要流式处理:Python 用
cursor.fetchmany(100),Go 用rows.Next(),避免一次性 load 全部到内存
真正麻烦的是字段内容本身不可控——比如用户上传的 PDF 存进 LONGBLOB,单条就 200MB。这种场景下,分批逻辑得按“文件粒度”而不是“行数粒度”来设计,否则一次 fetch 就 OOM。


















