再次了解max_allowed_packet

news/2024/11/17 10:25:48/

MySQL的参数很多,当出现问题时,往往就是某个参数在作祟,一方面说明MySQL的控制灵活,另一方面就要求熟知常用的参数作用,才能在出现问题的时候快速定位。

曾经写过一篇《小白学习MySQL - max_allowed_packet》的文章,其中介绍了MySQL的max_allowed_packet参数,最近碰巧看到爱可生开源社区推送了《技术分享 | MySQL:max_allowed_packet影响了什么?》,在此借鉴一下,有助于更系统地了解这个参数。

max_allowed_packet表示MySQL Server或者客户端接收packet的最大大小,packet即数据包,MySQL Server和客户端都有这个限制。


数据包

每个数据包,都由包头、包体两部分组成,包头由3字节的包体长度、1字节的包编号组成。3字节最多能够表示2 ^ 24 = 16777216字节(16M),就是说,一个数据包的包体长度必须小于等于16M。

如果要发送超过16M的数据怎么办?

当要发送大于16M的数据时,会将数据拆分成多个16M的数据包,除最后一个数据包之外,其他数据包大小都是16M。而MySQL Server收到这样的包后,如果发现包体长度等于16M ,他就知道本次接收的数据由多个数据包组成,会先将当前数据包的内容写入缓冲区,然后接着读取下一个数据包,并将下一个数据包的内容追加到缓冲区,直到读到结束数据包,就接收到客户端发送的完整数据了。

那怎样算一个数据包?

  • 一个SQL是一个数据包

  • 返回查询结果时,一行数据算一个数据包。

  • 解析的binlog ,如果用MySQL客户端导入,一个SQL算一个数据包。

  • 在复制中,一个event算一个数据包。

下面我们通过测试来讨论max_allowed_packet的实际影响。


导入SQL文件受max_allowed_packet限制么?

如果SQL文件中有单个SQL大小超过max_allowed_packet,会报错,

##导出时设置 mysqldump --net-buffer-length=16M,这样保证导出的sql文件中单个 multiple-row INSERT 大小为 16M
mysqldump -h127.0.0.1 -P13306 -uroot -proot --net-buffer-length=16M \
--set-gtid-purged=off sbtest sbtest1 > /data/backup/sbtest1.sql##设置max_allowed_packet=1M##导入报错
[root@localhost data]# mysql -h127.0.0.1 -P13306 -uroot -proot db3 < /data/backup/sbtest1.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1153 (08S01) at line 41: Got a packet bigger than 'max_allowed_packet' bytes


导入解析后的binlog受max_allowed_packet限制么?

row格式的binlog,单个SQL修改的数据产生的binlog如果超过max_allowed_packet,就会报错。

在恢复数据到指定时间点的场景,解析后的binlog单个事务大小超过1G,并且这个事务只包含一个SQL,此时一定会触发max_allowed_packet的报错。

但是恢复数据的任务又很重要,怎么办呢?可以将binlog改名成relay log,用SQL线程回放来绕过这个限制。

查询结果受max_allowed_packet限制么?

查询结果中,只要单行数据不超过客户端设置的max_allowed_packet即可,

##插入2行20M大小的数据
[root@localhost tmp]# dd if=/dev/zero of=20m.img bs=1 count=0 seek=20M
记录了0+0 的读入
记录了0+0 的写出
0字节(0 B)已复制,0.000219914 秒,0.0 kB/秒
[root@localhost tmp]# ll -h 20m.img
-rw-r--r-- 1 root root 20M 6月   6 15:15 20m.imgmysql> create table t1(id int auto_increment primary key,a longblob);
Query OK, 0 rows affected (0.03 sec)mysql> insert into t1 values(NULL,load_file('/tmp/20m.img'));
Query OK, 1 row affected (0.65 sec)mysql> insert into t1 values(NULL,load_file('/tmp/20m.img'));
Query OK, 1 row affected (0.65 sec)##mysql客户端默认 --max-allowed-packet=16M,读取失败
mysql> select * from t1;
ERROR 2020 (HY000): Got packet bigger than 'max_allowed_packet' bytes##设置 mysql 客户端 --max-allowed-packet=22M,读取成功
[root@localhost ~]# mysql -h127.0.0.1 -P13306 -uroot -proot --max-allowed-packet=23068672 sbtest -e "select * from t1;" > /tmp/t1.txt[root@localhost ~]# ll  -h /tmp/t1.txt
-rw-r--r-- 1 root root 81M 6月   6 15:30 /tmp/t1.txt


load data文件大小受max_allowed_packet限制么?

load data文件大小、单行大小都不受max_allowed_packet影响,

##将上一个测试中的数据导出,2行数据一共81M
mysql> select * into outfile '/tmp/t1.csv' from t1;
Query OK, 2 rows affected (0.57 sec)[root@localhost ~]# ll -h /tmp/t1.csv
-rw-r----- 1 mysql mysql 81M 6月   6 15:32 /tmp/t1.csv##MySQL Server max_allowed_packet=16M
mysql> select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|             16777216 |
+----------------------+
1 row in set (0.00 sec)##load data 成功,不受 max_allowed_packet 限制
mysql> load data infile '/tmp/t1.csv' into table t1;
Query OK, 2 rows affected (1.10 sec)
Records: 2  Deleted: 0  Skipped: 0  Warnings: 0

binlog中超过1G的SQL,是如何突破max_allowed_packet复制到从库的?

从库slave io线程、slave sql线程可以处理的最大数据包大小由参数slave_max_allowed_packet控制。这是限制binlog event大小,而不是单个SQL修改数据的大小。

主库dump线程会自动设置max_allowed_packet为1G,不会依赖全局变量 max_allowed_packet。用来控制主库dump线程每次读取event的最大大小。

具体可以参考,

https://mp.weixin.qq.com/s/EfNY_UwEthiu-DEBO7TrsA

另外超过4G的大事务,从库心跳会报错,

https://opensource.actionsky.com/20201218-mysql/

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

c26de9fffb3e34dbf7a8f9cec4cfb60d.png

近期更新的文章:

《MySQL的安全解决方案》

《Oracle 21c对JSON支持功能增强》

《Oracle同英超联赛数据统计和展示的结合》

《翻译专业资格(水平)考试介绍》

《MySQL忘了账号密码,除了跑路,还能补救么?》

近期的热文:

《"红警"游戏开源代码带给我们的震撼》

文章分类和索引:

《公众号1000篇文章分类和索引》


http://www.ppmy.cn/news/402981.html

相关文章

翻译专业资格(水平)考试介绍

关于英语考试&#xff0c;无论是国际的&#xff0c;还是国内的&#xff0c;都有很多种&#xff0c;之前介绍过TOEIC《我们征服托业&#xff0c;还是被托业征服&#xff1f;》&#xff0c;国内比较专业的英语考试&#xff0c;全国翻译专业资格考试(CATTI)算是一个&#xff0c;他…

TiDB沙箱环境初体验

最近接触了国产数据库领域中很火的TiDB数据库&#xff0c;先不说技术层面&#xff0c;给我印象最深的&#xff0c;就是他的培训和文档支持体系&#xff0c;非常系统和全面&#xff0c;这和传统巨头Oracle的服务支持路径很像。 培训课程&#xff0c;由浅入深&#xff0c;适合不同…

Oracle同英超联赛数据统计和展示的结合

技术是为业务服务的&#xff0c;一直在各个领域被论证&#xff0c;毕竟有场景使用&#xff0c;才能体现出价值&#xff0c;否则只能自娱自乐了。 了解现代足球篮球联赛的朋友&#xff0c;可能知道&#xff0c;现在球场上产生的数据是相当多的&#xff0c;无论是从维度上&#x…

MySQL客户端对配置文件读取顺序的问题场景

我们都知道使用MySQL客户端来访问MySQL数据库时&#xff0c;会以一定的顺序读取不同位置的配置文件&#xff0c;但在一次做测试时&#xff0c;发现除了按照顺序读取默认的配置文件路径外&#xff0c;MySQL还有额外的读取配置文件的行为。如下是爱可生开源技术社区最近推送的一篇…

魔方的征途 - 魔方如何选择?

可能大多和我同岁的朋友&#xff0c;小时候都有一个"我们认为一定能复原"但实际"无法复原"的魔方&#xff0c;看着大神们"信手拈来"的复原过程&#xff0c;除了惊呼"这个不可能"外&#xff0c;好像没其他能做的了&#xff0c;有些凄凉…

Oracle 21c对JSON支持功能增强

在这篇文章中《Oracle和JSON的结合》介绍了Oracle对JSON的支持&#xff0c;有朋友提了两个问题&#xff0c; 问题1&#xff0c;Oracle有没有字段可以直接存储JSON串并支持检索的&#xff1f; 问题2&#xff0c;试过几次&#xff0c;用来读取和约束还行&#xff0c;但是要用来存…

学习逆向知识之用于游戏外挂的实现.第三讲,通过游戏外挂.分析红色警戒金钱基址.以及确定基址小技巧....

分析红色警戒金钱基址.以及确定基址小技巧. 一丶基址简介 通过第二讲.我们寻找植物大战僵尸无限阳光.学习到了相关的逆向知识.以及认识了基址.动态地址. 静态地址的区别.现在我们拿红色警戒这款单击游戏进行练手. PS: 主要目的是分析数据.学习逆向知识.并为之所用.并不是教大家…

关于红色警戒2不能在Win1064位系统上运行的问题的解决

博主前两天去准姐夫家做客&#xff0c;中间我问他学生时代喜欢玩的游戏是什么&#xff0c;让他一个80后那么激动是这款经典到家的游戏&#xff0c;红警&#xff0c;临走的时候还跟我要我下次去的时候带着电脑跟他打一局。。。 回来的时候也没有太在意&#xff0c;今天突发奇想…