“Got packet bigger than max_allowed_packet”错误源于MySQL客户端和服务端传输时单个网络包超限,需同时调大两端的max_allowed_packet配置,服务端改[mysqld]段并重启,客户端按工具分别设置,且须验证实际生效值。

为什么 INSERT 或 LOAD DATA 会报 “Got packet bigger than max_allowed_packet”
MySQL 默认只允许单个网络包最大 4MB,一旦你插入超长 JSON、大字段文本、批量导入 CSV 或执行含巨量数据的 INSERT ... VALUES (...), (...), (...),就会触发这个错误。它不是数据太大存不下,而是 MySQL 客户端和服务端在传输时“一包装不下”,直接断掉。
关键点:这个限制在客户端和服务端是**分开配置**的,且必须**两边都调大**,否则其中一端仍会截断。
- 服务端(
mysqld)控制接收和返回的最大包,影响INSERT、LOAD DATA、SELECT ... INTO OUTFILE - 客户端(如
mysql命令行、Python 的pymysql、Java 的mysql-connector-java)也自带默认值,比如命令行客户端默认也是 4MB,不显式设置就卡在本地 -
max_allowed_packet是动态变量,但**仅对当前会话生效的 SET 不会影响后续连接或服务重启后的行为**
怎么永久修改 mysqld 的 max_allowed_packet
改错地方是常见坑:有人只改了 my.cnf 里的 [client] 段,结果服务端依然报错——那是给客户端看的,不是给 mysqld 进程用的。
必须改 [mysqld] 段,并重启服务:
[mysqld] max_allowed_packet = 64M
- 单位支持
K/M/G,不带单位默认是字节,别写成64000000这种易错数字 - 不要设得过大(比如 1G),可能引发内存碎片或 OOM,64M~256M 是较稳妥的生产常用范围
- 改完必须执行
sudo systemctl restart mysql(或mysqld),SET GLOBAL只是临时生效,且部分版本要求 SUPER 权限,还可能被某些托管平台(如阿里云 RDS)禁用
客户端也要同步调大:mysql 命令行、pymysql、jdbc 都要配
服务端调了,客户端没调,照样报错。比如你用 mysql -u root -p 登录后执行大 INSERT,还是失败——因为命令行客户端自己也有包大小限制。
- 命令行启动时加参数:
mysql --max_allowed_packet=64M -u root -p - Python +
pymysql:初始化连接时传参:connect(..., max_allowed_packet=67108864)(单位是字节) - Java JDBC URL 中加参数:
?maxAllowedPacket=67108864;注意不是max_allowed_packet(下划线无效) - Docker 启动 MySQL 时,通过
command覆盖默认配置:command: --max_allowed_packet=64M
验证是否生效 & 容易忽略的细节
别只查 SHOW VARIABLES LIKE 'max_allowed_packet',那只是当前会话看到的值。得确认三处:
- 服务端实际加载的值:
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_allowed_packet';" | grep mysqld(登录后查) - 客户端连接后的值:
SELECT @@max_allowed_packet;,这个值应与你启动客户端时指定的一致 - 如果用了连接池(如 HikariCP、SQLAlchemy),池子里的连接可能复用旧配置,需要重启应用或清空连接池
- 某些 ORM(如 Django)会在启动时预检连接,若此时服务端还没调好,它可能缓存错误配置,需重启整个服务
最麻烦的情况是:你改了 my.cnf,但 MySQL 实际读的是另一个路径的配置文件(比如 /etc/my.cnf.d/server.cnf),用 mysqld --verbose --help | grep "Default options" 确认真实加载路径。










