需同时调高服务端和客户端的max_allowed_packet值,例如设为512m,并验证生效;更稳妥方式是用--tab分导出或--hex-blob转义,避免sql语句超限。

mysqldump 备份时提示 Packet too large 错误
直接执行 mysqldump 备份含大 BLOB 的表时,常遇到类似错误:MySQL server has gone away 或明确提示 Packets larger than max_allowed_packet are not allowed。这不是连接中断,而是服务端拒绝接收超过限制的单个网络包——BLOB 字段内容被拼进 SQL 语句(如 INSERT INTO ... VALUES (...))后,整条语句可能远超默认的 4MB。
- 默认值因 MySQL 版本而异:5.7 默认 4MB,8.0 默认 64MB,但业务中几十 MB 的 BLOB 很常见
- 该限制作用于客户端与服务端**双向通信**:既影响
mysqldump发送的 INSERT 语句,也影响服务端返回的查询结果(如SELECT * FROM t WHERE id=1返回大 BLOB) - 只调客户端(如
mysqldump --max-allowed-packet=256M)不够——服务端max_allowed_packet必须同步调高,否则在解析语句阶段就拒绝
必须同时设置服务端和客户端的 max_allowed_packet
单独改某一边会失效。服务端参数控制 SQL 解析上限,客户端参数控制发送/接收缓冲区大小,二者需匹配且大于最大单条记录的序列化体积(含 SQL 模板开销)。
- 服务端修改(需重启或动态生效):
SET GLOBAL max_allowed_packet = 512*1024*1024;(512MB),或写入my.cnf的[mysqld]段:max_allowed_packet = 512M - 客户端命令行显式指定:
mysqldump --max-allowed-packet=512M -u root -p db_name table_name > backup.sql - 若用脚本调用,务必在
mysqldump命令中加--max-allowed-packet,别依赖配置文件里的 client 段——mysqldump实际只读取 [mysqldump] 段,不读 [client]
备份大 BLOB 更稳妥的方式:跳过 INSERT,用 --tab 或分块导出
即使调高 max_allowed_packet,把百 MB BLOB 拼进纯文本 SQL 仍风险高:内存占用陡增、导入时重放慢、文本编码易出错(尤其二进制数据转义失败)。
-
--tab=/path/to/dir将数据以制表符分隔的文本导出(.txt)+ 单独的建表语句(.sql),BLOB 以原始字节写入文件,不经过 SQL 转义,规避 packet 限制 - 对超大表,用
--where="id BETWEEN 1 AND 10000"分批次导出,配合--no-create-info避免重复建表 - 若必须用 SQL 格式,添加
--hex-blob:BLOB 以0x...十六进制形式输出,更安全但体积翻倍,此时max_allowed_packet需按放大后估算
验证是否真正生效及常见遗漏点
设完参数别急着备份,先验证服务端和客户端视角是否一致:
- 查服务端当前值:
SELECT @@global.max_allowed_packet;(注意是 global,非 session) - 查
mysqldump实际使用的值:加--verbose --debug-info运行一次小表导出,日志里会打印max_allowed_packet: 536870912 - 容易漏掉的是:Docker 容器启动时未透传
--max-allowed-packet参数;Kubernetes 中 ConfigMap 更新后未滚动重启 Pod;云数据库(如阿里云 RDS)需在控制台修改参数组并重启实例,不能直接 SET GLOBAL
实际备份前,用 SELECT OCTET_LENGTH(blob_col) FROM tbl ORDER BY 1 DESC LIMIT 1; 查下最大 BLOB 体积,再预留 2–3 倍空间设 max_allowed_packet——这个数字比文档里的“建议值”管用得多。











