bug描述

Oracle 最新发布的版本 5.6.22 中有这样一个关于GTID的bugfix,在主备场景下,如果我们在主库上 SET GLOBAL GTID_PURGED = "some_gtid_set",并且 some_gtid_set 中包含了备库还没复制的事务,这个时候如果备库接上主库的话,预期结果是主库返回错误,IO线程挂掉的,但是实际上,在这种场景下主库并不报错,只是默默的把自己 binlog 中包含的gtid事务发给备库。这个bug的造成的结果是看起来复制正常,没有错误,但实际上备库已经丢事务了,主备很可能就不一致了。

背景知识

一) binlog GTID事件

binlog 中记录的和GTID相关的事件主要有2种,Previous_gtids_log_event 和 Gtid_log_event,前者表示之前的binlog中包含的gtid的集合,后者就是一个gtid,对应一个事务。一个 binlog 文件中只有一个 Previous_gtids_log_event,放在开头,有多个 Gtid_log_event,如下面所示

二) 备库发送GTID集合给主库

我们知道备库的复制线程是分IO线程和SQL线程2种的,IO线程通过GTID协议或者文件位置协议拉取主库的binlog,然后记录在自己的relay log中;SQL线程通过执行realy log中的事件,把其中的操作都自己做一遍,记入本地binlog。在GTID协议下,备库向主库发送拉取请求的时候,会告知主库自己已经有的所有的GTID的集合,Retrieved_Gtid_Set + Executed_Gtid_Set,前者对应 realy log 中所有的gtid集合,表示已经拉取过的,后者对应binlog中记录有的,表示已经执行过的;主库在收到这2个总集合后,会扫描自己的binlog,找到合适的binlog然后开始发送。

三)主库如何找到要发送给备库的第一个binlog

主库将备库发送过来的总合集记为 slave_gtid_executed,然后调用 find_first_log_not_in_gtid_set(slave_gtid_executed),这个函数的目的是从最新到最老扫描binlog文件,找到第一个含有不存在 slave_gtid_executed 这个集合的gtid的binlog。在这个扫描过程中并不需要从头到尾读binlog中所有的gtid,只需要读出 Previous_gtids_log_event ,如果Previous_gtids_log_event 不是 slave_gtid_executed的子集,就继续向前找binlog,直到找到为止。

这个查找过程总会停止的,停止条件如下:

找到了这样的binlog,其Previous_gtids_log_event 是slave_gtid_executed子集

在往前读binlog的时候,发现没有binlog文件了(如被purge了),但是还没找到满足条件的Previous_gtids_log_event,这个时候主库报错

一直往前找,发现Previous_gtids_log_event 是空集

在条件2下,报错信息是这样的

Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.

其实上面的条件3是条件1的特殊情况,这个bugfix针对的场景就是条件3这种,但并不是所有的符合条件3的场景都会触发这个bug,下面就分析下什么情况下才会触发bug。

bug 分析

假设有这样的场景,我们要用已经有MySQL实例的备份重新做一对主备实例,不管是用 xtrabackup 这种物理备份工具或者mysqldump这种逻辑备份工具,都会有2步操作,

导入数据

SET GLOBAL GTID_PURGED ="xxxx"

步骤2是为了保证GTID的完备性,因为新实例已经导入了数据,就需要把生成这些数据的事务对应的GTID集合也设置进来。

正常的操作是主备都要做这2步的,如果我们只在主库上做了这2步,备库什么也不做,然后就直接用 GTID 协议把备库连上来,按照我们的预期这个时候是应该出错的,主备不一致,并且主库的binlog中没东西,应该报之前停止条件2报的错。但是令人大跌眼镜的是主库不报错,复制看起来是完全正常的。

为啥会这样呢,SET GLOBAL GTID_PURGED 操作会调用 mysql_bin_log.rotate_and_purge切换到一个新的binlog,并把这个GTID_PURGED 集合记入新生成的binlog的Previous_gtids_log_event,假设原有的binlog为A,新生成的为B,主库刚启动,所以A就是主库的第一个binlog,它之前啥也没有,A的Previous_gtids_log_event就是空集,并且A中也不包含任何GTID事件,否则SET GLOBAL GTID_PURGED是做不了的。按照之前的扫描逻辑,扫到A是肯定会停下来的,并且不报错。

bug 修复

官方的修复就是在主库扫描查找binlog之前,判断一下 gtid_purged 集合不是不比slave_gtid_executed大,如果是就报错,错误信息和条件2一样 Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.

详细的bugfix请看revno: 6211

mysql auto position_MySQL内核月报 2015.01-MySQL · 捉虫动态· 设置 gtid_purged 破坏AUTO_POSITION复制协议-阿里云开发者社区...相关推荐

  1. MySQL内核月报 2014.09-MySQL· 捉虫动态·auto_increment

    背景: Innodb引擎使用B_tree结构保存表数据,这样就需要一个唯一键表示每一行记录(比如二级索引记录引用). Innodb表定义中处理主键的逻辑是: 1.如果表定义了主键,就使用主键唯一定位一 ...

  2. MySQL内核月报 2014.10-MySQL· 捉虫动态·binlog重放失败

    背景 在 MySQL 日常维护中,要回滚或者恢复数据,我们经常会用 binlog 来在数据库上重放,执行类似下面的语句: mysqlbinlog mysql-bin.000001 | mysql -h ...

  3. mysql linux改user_linux mysql误修改user表导致无法root用户登录,求大神帮助。-问答-阿里云开发者社区-阿里云...

    linux mysql误修改user表导致无法root用户登录,急救!!! mysql> select user,host,password from user; user host passw ...

  4. mysql查询关键字报错_mysql中in关键字查询时的问题? 400 报错-问答-阿里云开发者社区-阿里云...

    之前也遇到过类似的问题,就是in关键字指定的范围没有数据,会出错######改用exists呢######不行######用join 链接查询过滤一下算了######我是这么做了,但是现在我就想知道, ...

  5. jfinal mysql读写分离_在JFinal中对数据库读写分离的实现:报错 -问答-阿里云开发者社区-阿里云...

    频繁使用 use(configName) 没有任何性能问题,仅仅是为变量赋一个 string 值而已,完全可以忽略######@JFinal######我现在也使用,读用的是视图model,写操作使用 ...

  6. mysql默认乐观锁悲观锁_MySQL中悲观锁和乐观锁到底是什么?-阿里云开发者社区...

    索引和锁是数据库中的两个核心知识点,隔离级别的实现都是通过锁来完成的 按照锁颗粒对锁进行划分 ? 锁用来对数据进行锁定,我们可以从锁定对象的粒度大小来对锁进行划分,分别为行锁.页锁和表锁. 行锁就是按 ...

  7. mysql space id_MySQL8.0新特性:增加系统文件追踪space ID和物理文件的映射-阿里云开发者社区...

    update:从8.0.11开始,又改成了打开全部ibd文件,但是改成了并行扫描 Note1: 本文所有代码相关的内容都是基于MySQL8.0.3,而目前版本还处于RC和快速开发的状态,不排除后面的版 ...

  8. mysql join 索引 无效_ORACLE MYSQL中join 字段类型不同索引失效的情况-阿里云开发者社区...

    ORACLE MYSQL中join 字段类型不同索引失效的情况 重庆八怪 2016-12-29 780浏览量 简介: 关于JOIN使用不同类型的字段类型,数据库可能进行隐士转换,MYSQL ORACL ...

  9. mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区

    关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...

最新文章

  1. 数据库名、数据库实例、全局数据库名、服务名、SID等的区别
  2. SMO算法(比较好的讲解)
  3. sysbench mysql测试_使用sysbench对MySQL进行测试
  4. python asyncio_Python 的异步 IO:Asyncio 简介
  5. sha java 应用_Java中常用的加密算法应用MD5,SHA,RSA
  6. robot framework学习五——AutoltLibrary库
  7. hping3发送MTU大包无法正确设置DF标志patch
  8. Jrebel激活破解
  9. PSP金手指下载及使用方法和图文教程
  10. 机器学习实战 | SKLearn入门与简单应用案例
  11. ubuntu下安装git安装及使用
  12. 微信小程序豆瓣评分实现搜索功能
  13. 飞机机身结构主要分三种,现在大部分飞机都用第三种
  14. ADAS/AD控制器模块开发11 - UDS与配置、校准
  15. 最有价值证书——ITIL名列第三
  16. Mac系统原生支持NTFS格式硬盘
  17. 主动降噪耳机那些事儿(一)
  18. 代理加速 gradle 构建
  19. 将opera强制的搜狗转为百度搜索
  20. 成为富人的十大心理特质

热门文章

  1. Spark之源码二次开发
  2. 计算机32位可以修改吗,32位能改64位吗
  3. 五分钟学GIS | 室内导航
  4. PPT基础(十六)文本对齐
  5. 车联网上云最佳实践(七)
  6. Excel如何快速录入月份序列
  7. 袋鼠云携手阿里云,打造梦想小镇马拉松大数据指挥中心
  8. HTML5系列代码:设置页面背景图像
  9. 将APP保卫战进行到底--为你的APP添加四道防线
  10. 中国噪音计市场趋势报告、技术动态创新及市场预测