mysql超大表处理方式是_第29问:MySQL 的复制心跳说它不想跳了

4752c2c4657e9fa50ce9f7f20ff642c9.png

问题

最近年底,大家的数据库经常跑批量大事务,会发现复制突然断开,报错“心跳与本地信息不兼容”:

9bb685ad1d68c85b6a7011921fad7358.png

会是什么原因?

实验

我们先来复现一下,再进行分析。

宽油,做一对主从数据库:

b241a5fb5d0a302cd7bf1936c97ca067.png

我们先造一个 500M 的空文件,下一步有用:

10b41b60de5004a6e70f6feaa7f0039b.png

再制造一张大表,这里用到了之前的造表法,不同的是使用了一个 longblob 字段,让少数的几行记录就能占用很大的 binlog 空间,方便我们后面做实验。

这里的 longblob 字段,用到了上一步我们做的空文件,

4becddb0a6e9c4525873e4ac7d177442.png

这样我们获得了一个行数较少,但体积很大的表。

现在起两个会话,一个事务造表 t2,一个事务造表 t3,并同时提交操作,以下举例其中一个事务:

8970c45fc9ddb30bb893dcbc1d28c12a.png

这样就获得了一个超大的 binlog,一共 32G,前 16G 是一个事务,后 16G 是另一个事务。

2918ba3581c3d903c099938e3626cced.png

小贴士
一个事务超过 binlog 的限制大小(最大 1G),就会在事务后直接切换到新的 binlog。
在同一个 binlog 中,我们想让一个超大事务后再记录一个事务,所以让两个事务同时提交,放在同一个提交组中。


查看一下 master 上的 GTID,最后两个事务分别是 25 和 26:

265f3187415435748552ce952da0997b.png

下面登录到 slave上,开始表演:

58e2d4aba6a21905c5345388e73bbb98.png

我们先重置 GTID 和复制状态,然后骗 slave 说它已经接到了 1-25 事务,要从 26 号事务开始传输,也就是从 32G binlog 的中间位置开始传输。

然后开始复制的 IO 线程,过十几秒,就可以看到复制报错:

04ca995d63df45550441017b5bdc7d6f.png

查看 Error log:

2043e0b7eb61ac30ac4ff20116ff3e98.png

和我们想要复现的报错一样。

下面我们来看一下原理:

这个复现中有几个要素:

  1. 从报错得知,报错与心跳有关,复制线必须配置复制心跳。
  2. 一个 binlog 中包含两个事务,第一个事务超过 4G。(我们在复现中为了方便,将第二个事务也做成了大事务,这一点不是必须的)。
  3. 从大事务后的位置,开始进行 binlog 复制传输。

我们用 tcpdump 抓个包:

73759d854fcdc118c767bdd5c114a192.png

用 wireshark 解开抓包,找到有问题的包(这里怎么找,我们分析后会有方法):

244fd23483e7fbe9888891bd7245e640.png

我们来分析一下包结构,这里我们将包的内容誊写下来,方便大家阅读:

首先阅读,https://dev.mysql.com/doc/internals/en/mysql-packet.html,了解 MySQL 的客户端网络包头结构:

da5c41d1461c2cf7aeead0a015fd8c1c.png

将我们的包对应上去:

d0fc663183579955a7285783af9b230c.png

其后的一位 00,是 MySQL 的 command type(https://dev.mysql.com/doc/internals/en/command-phase.html),在此没有意义,我们将其忽略,

再继续阅读,https://dev.mysql.com/doc/internals/en/event-header-fields.html,了解 binlog event 的头结构如下:

9203ac773a9b18ef01464f564df83278.png

将我们的包对应上去:

5ce07a1eef786f9a6397239c0aa1afed.png

接下来是个字符串,明显是一个 binlog 的名字,最后四个字节(下图中用黄色标注)是 checksum,

673d426bd29e99d1c700803f2cfd30a2.png

至此我们完成了一个心跳包的解析,并没有看出严重的问题,不妨往前再找一个心跳包看看规律:

975d44fd9b012ddc5bca616b3cf1a4d5.png

我将重点在图中标注,就是 next_position 的位置,在这个包中为 0xfa000557,而其下一个包中为 0x19400583,明显后面的 next_position 比前面的 next_position 小,这个不符合常理。

而 MySQL 的报错 heartbeat is not compatible with local info,也是在报这个问题:心跳包中的 position 不应比当前的 position 小。

那是什么导致了这个问题,我们注意到 next_position 的字段长只有 4 字节:

7c5c9745b016c5063606201562e1a0aa.png

也就是说,该字段最大值为 2 的 31 次方,也就是 4G,当前 binlog 的位置大于 4G 时,该字段就会溢出。也就是说,之前我们看到的位置 0x19400583,实际丢掉了最高的一位,应当是 0x119400583。

这也就导致了 binlog event 传输时,next_position 突然会变小,心跳机制会检查到这个变化,产生报错。

那我们怎么解决这个问题?

目前可能的方法有以下两种:

  1. 别用大事务,别用大事务,别用大事务。数据库系统本来就不是为大事务设计的,总会踩到不少坑。
  2. 停用心跳机制,这个问题并不是心跳机制带来的问题,每个 binlog event 都会带有这个包头。只是心跳机制让问题暴露了出来。如果关掉,提出问题的心跳机制,那么复制对于网络故障就会不敏感,导致更大的问题。这种方式不推荐使用。

复盘

因为文章比较长,我们对逻辑进行一下复盘:

  1. 我们通过抓包分析,知道 binlog 传输的网络包里,next_position 只有 4 个字节,最大数值为 4G。
  2. 我们在 master 上做了一个超过 4G 的大事务,让 slave 从这个大事务后开始传输。此时 master 会发送一个心跳包。
  3. 心跳包中的 next_position 是 log event 在 binlog 位置,由于这个位置大于 4G,会被截断,导致 next_position 比实际的小。

slave 收到心跳包,进行检测时发现 next_position 比实际的小,进行报错。

以上只是一种容易复现问题的场景。实际使用中,master 在一段时间不发送数据包后,或者特殊触发条件,都会发送心跳包。

对于一主多从的环境,每条复制链路的心跳是单独发送的,也就会导致多个 slave 的表现会有所不同,有的 slave 会触发报错,有的 slave 由于 master 没发送心跳包而不会触发报错。


最后送上几个小贴士:

1)我们如何快速找到有问题的包?

报错信息里已经标志了出错的 log position 是 423626115,转换成 16 进制为:0x19400583,找到由此数据的包即可。

2)一位一位读包太麻烦了,怎么办?

好办,先找到 server_id 的十六进制形式,以此为基准往后推定位数就可以。

比如我们的 server_id 是 19327,很容易找到基准位置。

3)报错里有一段乱码是啥?

最后这四位,是 MySQL 程序有缺陷,将包中的 checksum 作为文件名输出了,对程序逻辑没有影响。

0x11 是 17,对应 ASCII 码 "device control 1 character",键盘表达形式是 "ctrl + Q",打印形式就是 "^Q"。


本文相关的 MySQL 的 bug 列表:

https://bugs.mysql.com/bug.php?id=101948

https://bugs.mysql.com/bug.php?id=101955


关于 MySQL 技术内容,你们还有什么想知道的吗?赶紧****留言告诉小编吧!

1b35d1aef6d4879f1c164b1093e034cf.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/335792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java的访问控制修饰符_访问权限修饰符_访问权限修饰词

public > protected > (default) > private 1.public 修饰的,在任何地方都可以访问 2.protected 修饰的,在类内部、同一个包、子类中能访问 3.default 表示在本类中、同一个包中能访问,但是在代码中不可以直接写 default&#xff0…

red hat安装宝塔_只需几分钟即可安装Red Hat Container Development Kit(视频)

red hat安装宝塔自从我开始使用各种形式的OpenShift(例如带盒的Online,然后又作为容器化的图像)玩耍以来,没有什么比Red Hat Container Development Kit(CDK)的可用性令我兴奋。 该套件使您可以轻松地访问…

基于RTP的QOS算法简介

服务质量QoS(Quality of Service)用于评估服务方满足客户服务需求的能力。通过配置QoS,对企业的网络流量进行调控,避免并管理网络拥塞,减少报文的丢失率,同时也可以为企业用户提供专用带宽或者为不同的业务…

es修改type名称_ElasticSearch如何修改索引字段

一、需求 当es字段类型无法支撑业务需求,需要修改到字段类型的时候。例如修改字段类型从Integer变成double,这种情况下,是没办法修改es的字段的type的。 原因是一个字段的类型进行修改之后,ES会重新建立对这个字段的索引信息,ElasticsSearch的底层是Lucene库,字段类型修改…

MyEclipse for Windows 关于 java、jsp、xml、js、html 等文件的注释快捷键及注释格式介绍

文章目录java 的注释单行注释多行注释文本注释jsp 的注释第一种第二种第三种css 的注释js 的注释单行注释奇葩的单行注释多行注释文档注释xml 的注释html 的注释java 的注释 单行注释 public class HelloWorld{public static void main(String [] args){System.out.println(&…

sap 分摊分配不产生会计凭证的原因_SAP软件的物料分类账功能

物料账介绍物料分类账(Material Ledger)是SAP财务模块的重要功能之一,用于对标准价计价的物料进行差异处理。激活ML后,系统会在"工厂物料"层(或更细的层次)为每个物料建立子账簿,记录该物料在各个期间的数量、价值变化情况。月底运…

忽略异常_忽略已检查的异常,所有出色的开发人员都在这样做–基于600,000个Java项目...

忽略异常Github和Sourceforge上超过600,000个Java项目中的异常处理概述 Java是使用检查异常的少数几种语言之一。 它们在编译时强制执行,并且需要某种处理。 但是……在实践中会发生什么? 大多数开发人员实际上会处理任何事情吗? 他们怎么做…

数据结构【队列专题】

先进先出(First In First Out,FIFO)的线性序列,成为“队列”。 队列也是一种线性表,只不过它是操作受限的线性表,只能在两端操作: 一端进,一端出。进的一端成为队尾(re…

软件项目的命名规范/命名规则

文章目录项目名称目录名称包命名虚拟目录资源路径Java 代码命名属性文件 properties 命名xml文件命名jsp文件命名html文件命名js文件命名css文件命名图片文件命名数据库命名html标签的属性值命名规则项目名称 使用小串式命名法 项目名称使用英文,全部字母小写&…

数据结构【高精度专题】

// 高精度加法 // C A B, A > 0, B > 0 vector<int> add(vector<int> &A, vector<int> &B) {if (A.size() < B.size()) return add(B, A);vector<int> C;int t 0;for (int i 0; i < A.size(); i ){t A[i];if (i < B.size…

react java_独眼巨人React组织了Java 8库的寒武纪爆发

react java什么是独眼巨人React&#xff1f; Lambda表达式和默认方法在Java 8中的到来预示了Java语言十年来最大的结构性变化。 在此基础上构建了一些新的很酷的API&#xff0c;例如Stream, Optional, CompletableFuture最终Java开发人员可以以更实用的样式进行编码。 尽管这是…

oracle安装卡在create inventory_滴滴云服务器上安装Oracle12cR2单实例数据库

一、相关说明Oracle数据库是由美国甲骨文公司推出的一款优秀的关系型数据库。当前最新版为Database 19c。本文简述Oracle Database 12cR2在滴滴云主机上的安装过程。如需更权威的指导方法请参考Oracle官方安装文档。二、环境概述一台DC2云主机&#xff08;2c4g&#xff09;一个…

MyEclipse的build、clean、publish、clean(redeploy)的区别

文章目录buildcleanpublishclean(redeploy)新增了java文件或者修改了已有的java文件删除了java文件或者包修改了classes目录以外的文件build 就是将工程src目录的内容全新输出到工程的classes目录下&#xff0c;全面覆盖旧的文件&#xff0c;需要编译的会编译后再输出 clean …

jgroups_JGroups:无需额外基础架构的领导人选举

jgroups嗨&#xff0c;您好&#xff0c; 在本文中&#xff0c;我将展示如何在不使用任何其他基础架构&#xff08;例如Apache Zookeeper或Consul&#xff09;的情况下解决领导人选举的问题。 领导者选举是解决以下问题的一种常见方法&#xff1a;在分布式系统中&#xff0c;只…

【WebRTC---序篇】(二)Windows平台WebRTC源码编译

需要准备的东西 (一)一个强大的梯子(懂得都懂)!!!!!!!!! (二) 下载depot_tools Windows指定地址必须在此下载 打开这个页面,找 install depot_tools 这个关键字 请把他解压到C盘,并且设置到PATH环境变量种,且让它处于最顶端。 其他需要设置的额外变量 DEPOT_TOOLS_…

商品管理后台发布商品时,规格值组合的前端交互的实现逻辑

方案1&#xff1a;先计算总行数&#xff0c;再循环填充规格值 根据每种规格值数量计算得到总行数&#xff0c;如果下图有3种规格&#xff1a;长度、重量、大小&#xff0c;规格值个数分别为&#xff1a;3、3、2,3x3x218行。 规格种类有3种&#xff0c;于是写3层嵌套递归循环填…

python是什么牌子主机_python 收集主机信息

这篇文章是之前几篇的一个小综合。也是通过收集主机的一些参数信息&#xff0c;熟悉python里的文件读取&#xff0c;字符切割&#xff0c;字典存储等知识。文章结构&#xff1a;(1) 文章目的&#xff0c;需要收集的信息&#xff0c;并逐个分析如何获取信息。(2) 给出实现的pyth…

antlr idea 入门_ANTLR入门:构建简单的表达语言

antlr idea 入门这是该系列的第一篇文章。 本系列的目的是描述如何创建有用的语言和所有支持工具。 在本文中&#xff0c;我们将开始研究一种非常简单的表达语言。 我们将在语言沙箱中构建它&#xff0c;因此我们将其称为语言Sandy 。 我认为工具支持对于一种语言至关重要&am…

【WebRTC---源码篇】(五)WebRTC视频引擎

1. 视频数据的采集时间 2.视频分发器VideoBroadCaster

switch和toggle在软件开发中的含义和区别

switch和toggle这一对表示“切换”的单词&#xff0c;在计算机软件中我们能经常看到&#xff0c;很多时候口语中也会经常提及。但是&#xff0c;你想过它们之间有什么区别吗&#xff1f;没有区别&#xff1f;那你就大错特错了&#xff0c;区别还是很明显的&#xff0c;呵呵。 …