深入理解MySQL 5.7 GTID系列(五)gtid

转载自:老叶茶馆(iMySQL_WX)

作者:高鹏(重庆八怪)

原文地址:

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

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

本节将集中讨论下面三种GTID更新的时机,这部分相当重要,后面的故障案列会和这节有关。下面先来看一下他们的定义:

mysql.gtid_executed表:GTID持久化的介质,MySQL启动阶段会读取这个表来获取gtid_executed变量的值。

gtid_executed变量(show global variables):MySQL数据库已经执行了哪些GTID事务,处于内存中。show slave status中的executed_gtid_set也取自这里。

gtid_purged变量(show global variables):由于BINLOG文件的删除(如purge binary logfiles或者超过expire_logs_days设置)已经丢失的GTID事务,同时在搭建备库的我们使用set global gtid_purged变量来提示MySQL哪些GTID事务我已经执行过了。

这也是我们DBA通常能够观察到的几种GTID,有了前文的描述我们知道其中mysql.gtid_executed表是一种GTID持久化的介质,而gtid_executed变量和gtid_purged变量则对应了,gtid_state中的executed_gtidslost_gtids内存数据。他们分别表示MySQL数据库执行了哪些GTID事务,有哪些GTID事务由于BINLOG文件的删除已经丢失了。

其次我们先来达成一个共识gtid_executed变量一定是实时更新的不管主库和从库。我们的讨论分为主库,从库和通用从源码的角度进行详细讨论。并且约定都是打开GTID的情况下。最后给出最终总结。

一、主库修改时机

(1)BINLOG关闭

不生成gtid,mysql.gtid_executed/gtid_executed变量/gtid_purged变量均不更新。

(2)BINLOG打开

mysql.gtid_executed表修改时机

BINLOG发生切换(rotate)的时候保存直到上一个BINLOG文件执行过的全部GTID,它不是实时更新的。

栈帧如下:

其主要逻辑在gtid_state::save_gtids_of_last_binlog_into_table中我们在随后的部分讨论这个函数逻辑。

gtid_executed变量修改时机

如前文所述ordered_commit flush阶段生成GTID,在COMMIT阶段才计入gtid_executed变量,它是实时更新的。

栈帧如下:

其主要逻辑在gtid_state::update_gtids_impl中我们在随后的部分讨论这个函数逻辑。

gtid_purged变量修改时机

MySQL触发的清理BINLOG的情况下,比如purge binary logs to或者超过参数expire_logs_days设置的天数后自动删除,需要将丢失的GTID计入这个变量中。

栈帧如下:

其主要逻辑在MySQL_BIN_LOG::PURGE_LOGS中,我们随后查看其代码片段,同时MySQL_BIN_LOG::INIT_GTID_SETS函数是一个及其重要的函数,主要用在:

MySQL启动时候初始化整个GTID_STATE中的各种GTID_SET

MySQL删除BINLOG(如purge binary logfiles或者超过expire_logs_days设置)后需要确认gtid_purged变量(及gtid_state.lost_gtids)的值的时候。

随后我会单独一节来讲解MySQL GTID模块的初始化还会讲解这个函数。

二、主库修改时机源码函数分析

这里就对上面提到的主要逻辑函数进行分析

gtid_state::save_gtids_of_last_binlog_into_table函数逻辑

gtid_state::update_gtids_impl函数代码片段

mysql_binlog::purge_logs函数代码片段

三、从库修改时机

(1)BINLOG关闭或者BINLOG开启参数log_slave_updates关闭的情况

将他们放到一起因为他们的表现完全一样。

mysql.gtid_executed表修改时机

前面已经说过这种情况下从库没有办法通过BINLOG来持久化sql_thread执行过的GTID事务,只能通过实时更新mysql.gtid_executed表来保存,所以必须要要实时将GTID持久化到mysql.gtid_executed表中。实际上实时保存mysql.gtid_executed发生在commitpreper阶段之前,也就是最开始。但是对于主库来讲由于还没有生成GTID,那么则不能写入

栈帧如下:

其主要逻辑包含在commit_owned_gtids中。

GTID_EXECUTED变量修改时机

这个和主库一样实时更新,不做讨论。

gtid_purged变量修改时机

由于压根没有binlog来记录已经执行过的Gtid事务,所以gtid_purged变量实时更新

其更改处于整个ha_commit_trans的结尾如下:

栈帧如下(这个栈帧取值5.7.17):

当然其处理逻辑在gtid_state::update_gtids_impl_own_gtid中。

(2)BINLOG开启同时参数log_slave_updates开启的情况

这种情况sql_thread执行过的GTID事务可以通过BINLOG

进行维护,所以mysql.gtid_executed表和gtid_purged变量不需要实时更新。

mysql.gtid_executed表修改时机

和主库一致。及在进行日志切换的时候进行更新,不做讨论

gtid_executed变量修改时机和主库一样实时更新,不做讨论

gtid_purged变量修改时机

和主库一致,BINLOG删除时更新,不做讨论

四、从库修改时机源码函数分析

commit_owned_gtids函数逻辑:

gtid_state::update_gtids_impl_own_gtid函数逻辑片段,这个函数是5.7.17的,5.7.14没有逻辑放到了gtid_state::update_gtids_impl

五、通用更改时机

1、mysql.gtid_executed表修改时机

在reset master的时候清空本表

栈帧如下:

其主要逻辑在gtid_state::clear中。

set global gitd_purged的时候,设置本表

栈帧如下:

其主要逻辑在gtid_state::add_lost_gtids中。

2、gtid_executed变量修改时机

在reset master的时候清空本变量

栈帧同上

在set global gitd_purged的时候,设置本变量

栈帧同上

在MySQL启动的时候初始化设置GTID_EXECUTED变量,这个将在后面章节详细描述描述步骤。

3、gtid_purged变量修改时机

在reset master的时候清空本变量

栈帧同上

在set global gitd_purged的时候,设置本变量

栈帧同上

在mysql启动的时候初始化设置GTID_EXECUTED变量,这个将在后面章节详细描述描述步骤。

六、通用更改时机源码函数分析

gtid_state::clear函数逻辑

gtid_state::add_lost_gtids函数逻辑

七、本节小结

为了方便这里将上面的重点文字描述进行提取,去掉源码部分,方便大家阅读

1、主库修改时机(1)BINLOG关闭

不生成gtid,mysql.gtid_executed/gtid_executed变量/gtid_purged变量均不更新。

(2)BINLOG打开

mysql.gtid_executed表修改时机

BINLOG发生切换(rotate)的时候保存直到上一个BINLOG文件执行过的全部GTID,它不是实时更新的。

gtid_executed变量修改时机

如前文所述ordered_commit flush阶段生成GTID,在COMMIT阶段才计入gtid_executed变量,它是实时更新的。

gtid_purged变量修改时机

MySQL触发的清理BINLOG的情况下,比如purge binary logs to或者超过参数expire_logs_days设置的天数后自动删除,需要将丢失的GTID计入这个变量中。

2、从库修改时机

(1)BINLOG关闭或者BINLOG开启参数log_slave_updates关闭的情况

mysql.gtid_executed表修改时机

实时将GTID持久化到mysql.gtid_executed表中。

gtid_executed变量修改时机

它是实时更新的。

gtid_purged变量修改时机

由于压根没有BINLOG来记录已经执行过的GTID事务,所以gtid_purged变量实时更新

(2)BINLOG开启同时参数log_slave_updates开启的情况

mysql.gtid_executed表修改时机

进行日志切换的时候进行更新,同主库。

gtid_executed变量修改时机

实时更新,同主库。

gtid_purged变量修改时机

BINLOG删除时更新,同主库。

3、通用修改时机

mysql.gtid_executed表修改时机

(1)在reset master的时候清空本表。

(2)在set global gitd_purged的时候,设置本表。

gtid_executed变量修改时机

(1)在reset master的时候清空本变量。

(2)在set global gitd_purged的时候,设置本变量。

(3)在MySQL启动的时候初始化设置gtid_executed变量。

gtid_purged变量修改时机

(1)在reset master的时候清空本变量。

(2)在set global gitd_purged的时候,设置本变量。

(3)在MySQL启动的时候初始化设置gtid_purged变量。

此外reset master命令除了完成上述功能还会清理BINLOG,重新初始化BINLOG从序号1开始。而set global gitd_purged参数一般只有在reset master后使用,用于搭建GTID从库或者处理GTID从库故障。

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

1、主库和从库对于mysql.gtid_executed表,gtid_executed变量,gitd_purged变量

在各种情况下的修改时机

2、reset master做了什么关于GTID相关的工作

3、set global gitd_purged做了什么关于GTID相关的工作

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

社区介绍

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

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

扫码关注云+社区

领取腾讯云代金券