深入理解MySQL 5.7 GTID系列(四):mysql.gtid

转载自:老叶茶馆(iMySQL_WX)

作者:高鹏(重庆八怪)

原文地址:

https://www.jianshu.com/p/6ee969dc2c9b

本次将陆续推出系列文章共十篇,本文使用的源码版本为percona 5.7.14,也比较过5.7.17,5.6.25的源码版本,暂时没有能力比较全部的MySQL源码版本,如有误导还请见谅。

之所以把MySQL.GTID_EXECUTED表的作用和PREVIOUS GTID EVENT的改变放到一起进行描述是因为它们后面文章探讨的基础。这部分使用到了我自己使用C语言写的原生BINLOG解析工具INFOBIN

百度云盘下载如下:http://pan.baidu.com/s/1jHIWUN0

一、GTID EVENT

为什么要先描述什么是GTID EVENT呢?因为后面会用到,实际上在其中核心元素就是一个形如:

的一个GTID处于整个事务EVENT中的开始,用于描述这个事务的GTID是多少,当然在5.7中为了支持MTS其中还封装了LAST_COMMIT/SEQUENCE_NUMBER。那么使用INFOBIN工具查看一个INSERT单条语句完整事务的EVENT包括如下:

当然也可以使用MySQLBINLOG进行分析,只是格式稍微不那么友好。

二、GTID_EXECUTED表的作用

这一部分是重点中的重点,也是我以前一直疑惑的,请大家细细品读。

官方文档这样描述GTID_EXECUTED

也就是说GTID_EXECUTED表是GTID持久化的一个工具,如前文所描述GTID_STATE中的GET_EXECUTED_GTIDS/GET_LOST_GTIDS/GET_GTIDS_ONLY_IN_TABLE/GET_PREVIOUS_GTIDS_LOGGED这些数据都是存储在内存中的,那么在数据库重启后需要进行初始化,那么这需要读取GTID持久化的介质,我们可以发现GTID_EXECUTED是一个INNODB表建表语句如下,并且我们可以手动更改它,但是千万不要这么干:

那么在5.7.5以前没有GTID_EXECUTED表不是也没有问题吗?其实除了GTID_EXECUTED表以外我们还有一个GTID持久化的介质那就是BINLOG中的GTIDEVENT。所以总结一下GTID持久化介质:

GTID_EXECUTED

BINLOG中的GTIDEVENT

那么既然有了BINLOGGTIDEVENT进行持久化那么为什么还需要GTID_EXECUTED表呢?这实际上就是5.7.5过后的一个优化,我们可以反过来思考在5.6中如果使用了GTID做从库,从库如果不开启BINLOG并且同时设置LOG_SLAVE_UPDATES=TURE那么从库的执行过的GTID事务是没有办法持久化的。我们来一段5.6官方文档对于搭建GTID从库的其中一步:

开启BINLOG同时设置设置LOG_SLAVE_UPDATES=TURE必然造成一个问题,实际上从库很多时候我们是不需要做级联SLAVE,设置LOG_SLAVE_UPDATES=TURE会造成需要额外的空间和性能开销。自然这种情况下我们需要另外的一种GTID持久化介质,而并不是BINLOG中的GTIDEVENT。为了解决这个问题,5.7中GTID_EXECUTED表应运而生了。然而GTID_EXECUTED表是否需要实时更新呢?显然在slave端不开启BINLOG或者开启BINLOG不设置LOG_SLAVE_UPDATES=TURE的情况下它需要实时更新,因为I/OTHREAD执行过得GTID是必须持久化的,而在主库上因为有BINLOGGTIDEVENT的存在他是不需要实时更新的,这样不同的对待方式也能够减轻负担提高性能。

同时在官方文档上也有相关描述它分为是否开始BINLOG进行描述,但是其描述并不是最详细的。所以这部分在后面我会进行详细描述。

三、PREVIOUSGTIDEVENT的改变

PREVIOUSGTIDEVENT是包含在每一个BINLOG的开头用于描述所有以前BINLOG所包含的全部GTID的一个集合(包括已经删除的BINLOG)如:

在5.6中如果不开启GTID,那么BINLOG是不会包含这个PREVIOUSGTIDEVENT的,但是在5.7中不开启GTID也会包含这个PREVIOUSGTIDEVENT,实际这一点的改变其意义也是非常巨大,简单的说他为快速扫描BINLOG(BINLOG_GTID_SIMPLE_RECOVERY=TURE)获得正确GTID集合提供了基础,否则将会扫描大量的BINLOG,从而浪费I/O性能,这是5.6中一个非常严重的问题,在5.7的官方文档这样描述:

当然这部分也会在后面进行详细的描述,这里只是简单提一下。那么我们通过MySQLBINLOGINFOBIN工具分别确认这一点。

5.6. 26 不开启GTID

MySQLBINLOG

INFOBIN

我们并没有发现PREVIOUSGTIDEVENT,也就是5.6如果不开启GTID则不包含PREVIOUSGTIDEVENT

5.7.14

MySQLBINLOG:

INFOBIN

我们清晰的看到这里包含了PREVIOUSGTIDEVENT,当然我们还发现了ANONYMOUSGTIDEVENT这也是5.7中变化,5.7中即使不开始GTID每个事务也包含也一个ANONYMOUSGTIDEVENT,虽然没有GTID但是它任然包含了LAST_COMMITTED/SEQUENCE_NUMBER

四、本节小结

学习完本节至少能够学习到:

1、什么是GTIDEVENT。包含什么重要元素。

2、为什么需要GTID_EXECUTED表及其作用。

3、5.7中PREVIOUSGTIDEVENT发生了哪些改变。

4、简单了解PREVIOUSGTIDEVENT的改变意味着什么。

对本文有任何疑问可扫码添加原文作者微信

社区介绍

DBGeeK社区的创建,是为了更好的提供一个DBA的交流和活动平台(QQ群:516293316)。社区通过技术交流,线上、线下活动的分享,不断帮助用户提升数据库技能、获取数据库最佳实践,帮助用户更好、更安全的使用数据库。【做中国最好的共享数据库技术知识的社区】

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180208B0ME6W00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券