侧边栏壁纸
博主头像
Setyg的博客

当秋风染红落叶的时候,就是新生~

  • 累计撰写 86 篇文章
  • 累计创建 66 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

MySQL 批写入大小限制 max_allowed_packet 配置实践

Setyg
2026-09-20 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

做批量写入时最常见的两个报错——ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes 和莫名其妙的 ERROR 2006 (HY000): MySQL server has gone away——大概率是同一个原因:单条 SQL 语句超过了 max_allowed_packet 的限制。本文整理这个参数的默认值、三种修改方式(配置文件 / SET GLOBAL / SET PERSIST)、客户端侧同样要改的地方,以及改完之后常见的「为什么没生效」。

一、max_allowed_packet 是什么

max_allowed_packet 限制的是单个网络包的大小,实际效果就是:一条 SQL 语句、一行数据、一个 binlog event 的最大字节数。批量插入几百上千行、写入大文本 / BLOB、构造超长 IN (...) 列表时,整条语句会超限被拒。

默认值随版本变化,动手前先用 SHOW VARIABLES 确认真实值:

版本 默认值 说明
MySQL 5.7 4 MB 最容易撞到限制的版本
MySQL 8.0 64 MB 默认值已放宽,但大批量写入仍可能不够
MariaDB 10.2.4+ 16 MB 与 MySQL 取值不同,需单独确认

几个硬边界:

  • 取值范围 1024 字节 ~ 1073741824(1 GB),超过 1 GB 按 1 GB 处理。
  • 不是 1024 整数倍的值会被向下取整到 1024 的倍数。
  • 该变量同时有 global 和 session 两个作用域,且是动态变量,可以不重启修改。

二、方式一:修改配置文件(推荐,永久生效)

在配置文件的 [mysqld] 段中加入(注意单位可以直接写 M / G):

[mysqld]
max_allowed_packet=100M

100M 等价于 104857600。也可以直接写字节数:

[mysqld]
max_allowed_packet=104857600

各平台配置文件位置:

平台 常见路径
Windows my.ini,通常在 C:\ProgramData\MySQL\MySQL Server 8.0\(ProgramData 是隐藏目录),或安装目录下
CentOS / RHEL /etc/my.cnf
Debian / Ubuntu /etc/mysql/my.cnf,实际配置常拆分在 /etc/mysql/mysql.conf.d/mysqld.cnf
macOS(Homebrew) /opt/homebrew/etc/my.cnf 或 /usr/local/etc/my.cnf

不确定当前实例读的是哪份配置时,可以查启动参数:

SHOW VARIABLES LIKE 'datadir';   -- 顺带确认实例身份
-- 或直接看进程启动参数中的 --defaults-file
-- Windows: 服务属性 → 可执行文件路径;Linux: ps -ef | grep mysqld

改完必须重启 MySQL 服务(Windows 下 net stop mysql80 && net start mysql80,或 services.msc 里重启服务;Linux 下 systemctl restart mysqld)。

三、方式二:SET GLOBAL(临时,立即生效)

不重启、马上生效:

SET GLOBAL max_allowed_packet = 1073741824;

两个必须知道的限制:

  • 只对新建立的连接生效,已经连上的连接(以及连接池里空闲的那些)仍然用旧值,需要重连或重启应用。
  • 重启后失效,属于一次性救急手段,长期配置还是要落到配置文件。

也可以只改当前会话(不能超过 global 值):

SET SESSION max_allowed_packet = 33554432;

四、方式三:SET PERSIST(MySQL 8.0,改完即持久化)

MySQL 8.0 提供了折中方案:既立即生效,又写入 mysqld-auto.cnf 在重启后保留,不用手工编辑配置文件。

SET PERSIST max_allowed_packet = 1073741824;

需要 SYSTEM_VARIABLES_ADMIN 权限。不想要这条持久化配置时用 RESET PERSIST max_allowed_packet; 清除。

三种方式对比

方式 是否立即生效 是否重启保留 适用场景
配置文件 + 重启 否 是 常规配置,最稳妥
SET GLOBAL 是(仅新连接) 否 线上救急、临时放宽
SET PERSIST(8.0) 是(仅新连接) 是 不想重启又要长期生效

五、客户端侧也要同时放宽

实际可用的包大小取客户端与服务端的较小值,只改服务端可能仍然报错。命令行工具需要显式指定:

# mysql 客户端
mysql --max-allowed-packet=256M -u root -p

# mysqldump 导出/恢复含大字段的数据
mysqldump --max-allowed-packet=256M -u root -p db_name > backup.sql

# 也可以写进配置文件,让客户端工具自动读取
[mysqldump]
max_allowed_packet=256M

应用侧注意三点:

  • JDBC(Connector/J)有同名的 maxAllowedPacket 连接参数,默认值随驱动版本变化,需要时在连接串里显式指定。
  • 服务端用 SET GLOBAL 放宽后,连接池中的存量连接不会自动更新,要让应用重启或等连接自然轮换。
  • 批写入本身也建议控制单批条数(如每批 500~1000 行),把「单条语句不要太大」当成常规约束,比单纯把参数调到 1 G 更稳。

六、验证与排查

-- 查看当前有效值
SHOW VARIABLES LIKE 'max_allowed_packet';
SELECT @@global.max_allowed_packet, @@session.max_allowed_packet;

-- 查看是否被 SET PERSIST 写入了持久化配置(8.0)
SELECT * FROM performance_schema.persisted_variables;

常见「改了没生效」的原因:

  • 改完没重启,或只做了 SET GLOBAL 却在旧连接上继续跑。
  • 配置段写错:写进 [client] / [mysql] 只影响客户端,服务端必须放在 [mysqld]。
  • 改错了配置文件:机器上有多份 my.ini / my.cnf,实例实际读的不是正在编辑的这一份,以启动参数 --defaults-file 为准。
  • 只改了服务端:客户端工具或驱动仍是旧值,取较小值后依旧报错。

另外两点容易被忽略:

  • 主从 / 组复制环境:从库的 max_allowed_packet 不应小于主库,否则大事务对应的 binlog event 在从库上会应用失败,建议全集群统一取值。
  • 不要盲目设 1 G:缓冲区按需分配、不是每个连接都立刻占用,但极端情况下会给单连接带来更大的内存峰值。按「实际最大单条语句的 2~4 倍」估算即可,比如峰值语句 20 MB,设置 64M 已经足够。

七、速查卡

# Linux: /etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf
# Windows: my.ini(常在 C:\ProgramData\MySQL\MySQL Server 8.0\)
[mysqld]
max_allowed_packet=100M        # 100M = 104857600 字节,重启生效
SET GLOBAL  max_allowed_packet = 1073741824;  -- 立即生效,仅新连接,重启失效
SET SESSION max_allowed_packet = 33554432;    -- 仅当前会话
SET PERSIST max_allowed_packet = 1073741824;  -- 8.0,重启保留
SHOW VARIABLES LIKE 'max_allowed_packet';     -- 验证
mysql     --max-allowed-packet=256M -u root -p     # 客户端侧同步放宽
mysqldump --max-allowed-packet=256M -u root -p db > backup.sql
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区