max_allowed_packet必须在服务端配置文件[mysqld]段设置并重启,客户端连接也需同步配置,仅SET GLOBAL为临时补丁;超限报错如“MySQL server has gone away”或“Got packet bigger than 'max_allowed_packet'”,日志含“Packets larger than max_allowed_packet are not allowed”即可确认;永久修改需在/etc/my.cnf等文件中设max_allowed_packet=256M并重启服务,同时配齐[client]、[mysqldump]及应用客户端参数,避免OOM与崩溃风险。

直接说结论:max_allowed_packet 必须在服务端配置文件中设、客户端连接时再确认一遍,只用 SET GLOBAL 是临时补丁,不是解决方案。
查当前值和确认是否真超限
报错如 Got a packet bigger than 'max_allowed_packet' bytes 或 MySQL server has gone away,先别急着调大,先确认是不是它导致的:
- 登录 MySQL 后执行
SHOW VARIABLES LIKE 'max_allowed_packet';,返回值单位是字节(比如4194304= 4MB) - 对比你正操作的数据:一个 8MB 的 base64 图片字符串、一条含 200 个 JSON 字段的
INSERT、或mysqldump导出的单行超长 SQL —— 这些都可能突破默认限制 - 注意日志里是否紧跟着
Packets larger than max_allowed_packet are not allowed,这是关键判定依据
永久修改必须改 [mysqld] 段并重启
临时 SET GLOBAL max_allowed_packet = 67108864; 只影响当前运行实例,且已有连接不生效;真正要落地,得改配置文件:
- Linux 常见路径:
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf;Windows 查my.ini(可能藏在C:\ProgramData\MySQL\) - 在
[mysqld]段下添加一行:max_allowed_packet = 256M(支持K/M/G后缀,比写268435456更安全) - 改完必须重启服务:
sudo systemctl restart mysql(Ubuntu/Debian)或sudo service mysqld restart(CentOS/RHEL) - 别漏掉复制从库:如果用了主从,从库的
[mysqld]也得同步改,否则LOAD DATA或大事务会中断复制
客户端侧不配,照样失败
服务端设成 512M,不代表你用 mysql 命令行或 Python 脚本就能发 512M 的包——各客户端有独立限制:
-
mysql命令行工具:在~/.my.cnf的[client]段加max_allowed_packet = 256M,或启动时加参数mysql --max-allowed-packet=268435456 -u root -p - Python
mysql-connector:初始化连接时显式传参max_allowed_packet=268435456,光设服务端没用 - JDBC:URL 中加
&maxAllowedPacket=268435456(单位字节) -
mysqldump和mysqlimport:它们属于客户端工具,同样要单独配--max-allowed-packet,否则导出/导入大表仍报错
设太大反而容易触发 OOM 或崩溃
这不是“越大越好”的参数。设成 1G 看似保险,但实际埋了硬伤:
- 每个新连接都会预分配一块对应大小的内存缓冲区,100 个并发连接就吃掉 100GB 内存(哪怕没传大包)
- MySQL 5.6 及更老版本对 >128M 的 packet 处理有已知 crash 风险,尤其在开启 binlog 或 GTID 场景下
- 应用层没做输入校验时,恶意或 bug 导致的超大无效 payload 会卡死连接,拖慢整个实例
- 建议按业务最大单条数据体积 × 1.5 设置,比如最长大 BLOB 是 8MB,那就设
12M或16M;上线前务必在测试环境压测内存和连接稳定性
最容易被忽略的是:服务端、客户端、中间件(比如 ProxySQL、MaxScale)三者中任意一环的 max_allowed_packet 设低了,整条链路就断。别只盯着 MySQL 自己的配置文件。











