一.GTID的基本概念
GTID特性是从MySQL5.6开始加入的一个强大特性,又叫全局事务ID,是一个已提交事务的编号。MySQL会为每一个DML/DDL操作增加一个唯一标记叫做GTID,这个标记在整个复制环境中都是唯一的。主从环境中主库的DUMP线程可以直接通过GTID定位到需要发送的binlog位置,而不再需要指定binlog的文件名和POS号,因此切换很方便。
二.GTID的表示
GTID是由server_uuid和gno组成的;GTID的表示主要有以下几个关注点:
(1)GTID:单个GTID,比如‘24985463-a536-11e8-a30c-5432223535e4:5’。对应源码中的类结构Gtid。源码中用sid代表前面的server_uuid,gno则用来表示后面的序号。
(2)gno:单个GTID后面的序号,上面的GTID其gno为5,这里的gno实际上是从全局计数器next_free_gno中获取的。
(3)GTID SET:一个GTID的集合,可以包含多个server_uuid,比如我们常见的executed_gtid,gtid_purged就是一个GTID SET。对应源码中的类结构Gtid_set,其中还包含一个sid_map用于表示多个server_uuid。
(4)GTID SET Interval:GTID SET中某个server_uuid可能包含多个区间比如‘1-5:7-10’。对应源码中的结构体Gtid_set::Interval
三.server_uuid的生成
我们可以看到GTID中均包含了一个server_uuid。server_uuid实际上是一个32字节+1字节(/0)的字符串。MySQL启动的时候会调用函数init_server_auto_options来读取auto.cnf文件。如果auto.cnf文件丢失,则会调用函数generate_server_uuid来生成一个新的server_uuid,但是需要注意这样GTID必然会发生改变。
下面是generate_server_uuid的部分代码
然而server_uuid的内部表示是binary_log::Uuid,核心就是一个16字节的内存空间,在GTID相关的Event中就会包含这个信息。
四.GTID的生成
GTID其实是在‘Commit’命令发起后,order commit 执行到flush阶段需要生成GTID Event的时候才会获取。MySQL内部维护了一个全局的GTID的计数器next_free_gno用于生成gno。可以参考Gtid_state::get_automatic_gno,部分代码如下:
五.gtid_executed表的作用
官方文档中描述gtid_executed是GTID持久化的一个介质。实例重启后所有的内存信息都会丢失,GTID模块初始化就需要读取GTID持久化介质。
表结构如下
另外还有一种GTID持久化的介质->binary log 中的GTID_LOG_EVENT,其中我们使用GTID做从库的时候,从库必须开启binlog同时设置log_slave_updates,使从库执行的GITD操作也记录在自己的binlog中,但是很多时候我们不需要做级联,设置log_slave_updates,会造成额外的空间和性能开销。因此虽然有两种GITD持久化介质,但是更多的还是以gtid_executed表为主。