什么max_allowed_pa​​cket足够大,为什么我需要更改它?


14

我在主从设置中安装了MySQL(5.5),并创建了另一个从服务器。

我停止了原来的从属服务器,转储了数据,复制并重新导入了它,然后运行良好。我注意到了原始从站的master_log pos,并使用这些命令将其设置在新的从站上

CHANGE MASTER TO MASTER_HOST='<ipaddress>', 
MASTER_USER='<username>', MASTER_PASSWORD='<password>', 
MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000851', 
MASTER_LOG_POS=15824150, 
MASTER_CONNECT_RETRY=10;

当我开始新的奴隶时,我得到了

Last_IO_Error:从二进制日志读取数据时,主机出现致命错误1236:'日志事件条目超过了max_allowed_pa​​cket; 增加master上的max_allowed_pa​​cket

但是,当我启动原始从属服务器时,它运行起来很好,并且现在已同步。

所以问题是:

  • 当前值是16M,我怎么知道要走多大?(我宁愿避免生产服务器的反复试验)。

  • 当原来的从属服务器很好时,为什么我需要增加主控板上的值,问题可能出在新的从属服务器上吗?

更新

正如Rolando在主机,旧从机和新从机上建议的那样,我将max_allowed_pa​​cket增加到1073741824,然后重新启动它们(SET GLOBAL max_allowed_packet = 1073741824;由于某些原因,似乎没有用)

现在最后一个IO错误与以前相同,但是现在我看到了

Last_SQL_Error:中继日志读取失败:无法解析中继日志事件条目。可能的原因是:主站的二进制日志已损坏(您可以通过在二进制日志上运行“ mysqlbinlog”来检查),从站的中继日志已损坏(可以通过在中继日志上运行“ mysqlbinlog”来检查)网络问题,或主从MySQL的错误。如果要检查主站的二进制日志或从站的中继日志,则可以通过在此从站上发布“ SHOW SLAVE STATUS”来知道其名称。

如果我在主文件上执行一个mysqlbinlog,它会用命令滚动很久很久很久-该文件为722M-如果我为从属中继日志执行该操作

错误:Log_event :: read_log_event()中的错误:“健全性检查失败”,data_len:38916267,event_type:69

错误:无法读取偏移量为253的条目:日志格式错误或读取错误。

我检查了变量,但所做的更改有效

mysql>显示变量LIKE'%max_allowed_pa​​cket%';

在新的从属设备上显示max_allowed_packetAND slave_max_allowed_packet,而在主设备上只有max_allowed_packet

所以我对母版进行了版本检查:

mysql> show variables LIKE '%version%';
+-------------------------+--------------------------------------+
| Variable_name           | Value                                |
+-------------------------+--------------------------------------+
| innodb_version          | 1.1.6                                |
| protocol_version        | 10                                   |
| slave_type_conversions  |                                      |
| version                 | 5.5.11-log                           |
| version_comment         | MySQL Community Server (GPL) by Remi |
| version_compile_machine | x86_64                               |
| version_compile_os      | Linux                                |
+-------------------------+--------------------------------------+

在新的奴隶上

mysql> show variables LIKE '%version%';
+-------------------------+--------------------------------------+
| Variable_name           | Value                                |
+-------------------------+--------------------------------------+
| innodb_version          | 5.5.32                               |
| protocol_version        | 10                                   |
| slave_type_conversions  |                                      |
| version                 | 5.5.32-log                           |
| version_comment         | MySQL Community Server (GPL) by Remi |
| version_compile_machine | x86_64                               |
| version_compile_os      | Linux                                |
+-------------------------+--------------------------------------+

这两个版本相距太远吗?


有一些有趣的东西在这里。希望这会有所帮助。
Sathish D

Answers:


18

最大化max_allowed_packet到1G是可以的。每当构造MySQL数据包时,它从一开始就不会跳到1G。为什么?

首先,您需要知道什么是MySQL数据包。书的第99页

了解MySQL内部

在第1-3段中对此进行了解释,如下所示:

MySQL网络通信代码是在假设查询总是相当短的前提下编写的,因此可以以一个块的形式发送到服务器并由服务器进行处理,这在MySQL术语中称为数据包。服务器为临时缓冲区分配内存以存储数据包,并且它请求足够完全容纳它。这种体系结构需要采取预防措施,以避免服务器用尽内存-限制数据包大小,此选项可以实现此目的。

与该选项有关的感兴趣的代码位于 sql / net_serv.cc中。看一下my_net_read(),然后跟随对my_real_read()的调用,并特别注意 net_realloc()

此变量还限制了许多字符串函数的结果的长度。有关详细信息,请参见sql / field.ccsql / intem_strfunc.cc

将其与MySQL文档进行比较max_allowed_packet

一个数据包或任何生成/中间字符串或mysql_stmt_send_long_data()C API函数发送的任何参数的最大大小。从MySQL 5.6.6开始,默认值为4MB,在此之前为1MB。

数据包消息缓冲区被初始化为net_buffer_length个字节,但在需要时可以增长到max_allowed_pa​​cket个字节。默认情况下,此值较小,以捕获较大(可能不正确)的数据包。

如果使用大的BLOB列或长字符串,则必须增加此值。它应该与要使用的最大BLOB一样大。max_allowed_pa​​cket的协议限制为1GB。该值应为1024的倍数;非整数将四舍五入到最接近的倍数。

通过更改max_allowed_pa​​cket变量的值来更改消息缓冲区大小时,如果客户端程序允许,还应该在客户端上更改缓冲区大小。在客户端,max_allowed_pa​​cket的默认值为1GB。某些程序(例如mysql和mysqldump)使您可以通过在命令行或选项文件中设置max_allowed_pa​​cket来更改客户端值。

有了这些信息,您应该很高兴MySQL将根据需要扩展和收缩MySQL数据包。因此,继续

主设备和从设备应该在谁传输数据(尤其是BLOB数据)方面进行匹配。

更新2013-07-04 07:03 EDT

从有关中继日志的消息中,您看起来像以下内容

  • 中继日志损坏
  • 一个好的主日志

建议

SHOW SLAVE STATUS\G
STOP SLAVE;
CHANGE MASTER TO
MASTER_LOG_FILE='(Relay_Master_Log_File from SHOW SLAVE STATUS\G)',
MASTER_LOG_POS=(Exec_Master_Log_Pos from SHOW SLAVE STATUS\G);
START SLAVE;

运行CHANGE MASTER TO清除所有中继日志,并从新日志开始。您将从在从站上执行的最后一个主BinLog事件(BinLog,位置)中复制。

试试看 !!!


谢谢,这很安全。但是我仍然不明白为什么当当前值与主站以及另一个工作正常的从站匹配时,我根本不需要更改它吗?
CodeMonkey

发生了其他事情,我添加了更多详细信息
CodeMonkey

1
仅供参考:当我重置复制过程并意外输入错误MASTER_LOG_FILE名称时,发生了这种情况。例如,使用mysql-bin.000001时,我应该用mysql-bin.000003SHOW MASTER STATUSCHANGE MASTER TO
Mikko Ohtamaa 2014年

8

令人尴尬的是,问题是日志的文件名不正确,导致出现奇怪的结果,使用正确的文件名重新导入,一切都很好,令人sha愧


非常感谢!您不是唯一一个犯此错误的人。
Mikko Ohtamaa 2014年

3
即使答案很傻,也总是值得发布答案。每个人都会犯傻,因为我们都是人。除了我们这些机器人。
约翰·亨特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.