问题

最近年末,你们的数据库常常跑批量大事务,会发现复制忽然断开,报错“心跳与本地信息不兼容”: 会是什么缘由?php

实验

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

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

mysql

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

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

这里的 longblob 字段,用到了上一步咱们作的空文件, 网络

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

如今起两个会话,一个事务造表 t2,一个事务造表 t3,并同时提交操做,如下举例其中一个事务: spa

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

小贴士

一个事务超过 binlog 的限制大小(最大 1G),就会在事务后直接切换到新的 binlog。设计

在同一个 binlog 中,咱们想让一个超大事务后再记录一个事务,因此让两个事务同时提交,放在同一个提交组中。

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

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

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

而后开始复制的 IO 线程,过十几秒,就能够看到复制报错:

查看 Error log:

和咱们想要复现的报错同样。

下面咱们来看一下原理:

这个复现中有几个要素:

从报错得知,报错与心跳有关,复制线必须配置复制心跳。

一个 binlog 中包含两个事务,第一个事务超过 4G。(咱们在复现中为了方便,将第二个事务也作成了大事务,这一点不是必须的)。

从大事务后的位置,开始进行 binlog 复制传输。

咱们用 tcpdump 抓个包:

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

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

将咱们的包对应上去:

将咱们的包对应上去:

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

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

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

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

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

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

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

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

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

别用大事务,别用大事务,别用大事务。数据库系统原本就不是为大事务设计的,总会踩到很多坑。

停用心跳机制,这个问题并非心跳机制带来的问题,每一个 binlog event 都会带有这个包头。只是心跳机制让问题暴露了出来。若是关掉,提出问题的心跳机制,那么复制对于网络故障就会不敏感,致使更大的问题。这种方式不推荐使用。

复盘

由于文章比较长,咱们对逻辑进行一下复盘:

咱们经过抓包分析,知道 binlog 传输的网络包里,next_position 只有 4 个字节,最大数值为 4G。

咱们在 master 上作了一个超过 4G 的大事务,让 slave 从这个大事务后开始传输。此时 master 会发送一个心跳包。

心跳包中的 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 列表:

关于 MySQL 的技术内容,大家还有什么想知道的吗?赶忙留言告诉小编吧!

php 判断心跳包报错,第29问:MySQL 的复制心跳说它不想跳了相关推荐

  1. 【报错笔记】项目使用了JSONArray类,导了import net.sf.json.JSONArray;包报错

    项目使用了JSONArray类,导了import net.sf.json.JSONArray;包报错 报错原因:net.sf.json添加的时候需要添加jdk的版本号 解决方案:在pom.xml中添加 ...

  2. yarn安装依赖包报错 error An unexpected error occurred: “https://registry.npm.taobao.orgnpm/element-ui: get

    yarn安装依赖包报错,error An unexpected error occurred: "https://registry.npm.taobao.orgnpm/element-ui: ...

  3. 解决Pycharm文件夹中同级目录导包报错的问题

    报错情况:导包报错,但程序仍然可以运行 https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 让这个可爱的宝藏女孩在 ...

  4. Mac解压Linux平台tar包报错:tar: Error reading Truncated input file

    1.报错:tar: Error reading Truncated input fileMac使用tar命令解压Linux平台tar包报错,需要安装gnu-tar来解压. 2.解决 # brew in ...

  5. 银河麒麟(linux)wireshark 打开抓包报错 The capture session could not be initiated on interface ‘enp2s0‘(You...

    版本:银河麒麟桌面操作系统V10(SP1) 内核:Linux 5.4.18-28.23-bj-generic CPU:Loongson-3A5000 终端输入 uname -m 查看 架构: loon ...

  6. win10添加计算机语言,Win10添加语言包报错“0x800F0950”怎么办?

    Win10添加语言包报错"0x800F0950"怎么办?在使用Win10系统的过程中,有时候我们需要添加语言,来实现一些工作需求,然而有用户遇到添加语言包失败的情况,系统提示错误代 ...

  7. 安装R包报错 [tcl] grab failed: window not viewable.的解决方案

    安装R包报错 [tcl] grab failed: window not viewable.的解决方案 ##方法一:用下代码自己选择镜像 chooseCRANmirror(graphics=F) ## ...

  8. R安装nCov2019包报错:Failed to install 'unknown package' from GitHub: schannel: failed to receive handsh

    在Rstudio中,安装nCov2019包报错:Failed to install 'unknown package' from GitHub: schannel: failed to receive ...

  9. 引入spring-boot-starter-redis包报错 :unknown

    springboot集成redis时,引入spring-boot-starter-redis包报错,maven找不到这个资源.如下图: 我的项目中,spring boot是 用的2.0.4版本. sp ...

最新文章

  1. Arcgis for JS扩展GraphicLayer实现区域对象的聚类统计与展示
  2. 系统提示一个程序正在被另一个程序调用,如何知道是被哪个程序调用
  3. asp.net mvc 中直接访问静态页面
  4. NOI.AC NOIP模拟赛 第四场 补记
  5. 中国汽车系统为Alfa Romeo首款紧凑型SUV电动车开发新型转向系统
  6. 网络安全——计算机网络拓扑图
  7. fleaphp 快速开发php框架
  8. 一个优质软件测试工程师简历,疯狂面试5家公司......
  9. 天地图key申请_国家地理信息公共服务平台 天地图
  10. ChatGPT插件与简要介绍(已收集70个)了解添加插件后的chatgpt能做什么
  11. NodeJS 创建静态资源服务器
  12. 《笑傲江湖》人名解读
  13. 块存储服务(Cinder)安装配置,这一篇就够了!
  14. poi doc转docx_文件批量操作之.doc转成.docx
  15. PPT制作--这不是技巧,而是常识 然而好多人并不知道 (hsyl007转载整理)
  16. 华师的入学计算机测试题,华师期末考试计算机练习题
  17. iPhone上Siri无法正常回应如何解决?
  18. 电脑开机黑屏,只有鼠标能动
  19. supervisor安装总结
  20. stc51单片机入门 c语言,STC51单片机入门 (C语言)

热门文章

  1. 前端学习(564):margin计算规则
  2. 前端学习(284):纯css实现翻书效果
  3. http:(3):http响应头信息
  4. csgo被会话踢出什么鬼_【解决方案】“CSGO游戏—断开连接,VAC无法验证会话”问题解决方案...
  5. 非类型模板参数(参考《C++ Templates 英文版第二版》)
  6. php代码里怎么写html代码_菜鸟青铜变白银!Python 项目代码写完了,然后怎么打包和发布?...
  7. python整数序列求和_Python从菜鸟到高手(14):序列的加法和乘法
  8. python tornado对接权限中心的sdk封装
  9. pgd 游戏教程 基地
  10. Hyperledger中数据存取的实现