实验环境

此次实验的环境如下

  • MySQL 5.7.25

  • Redhat 6.10

  • 操作系统账号:mysql

  • 数据库复制账号:repl

  • 复制格式:基于行的复制

IP地址 主从关系 复制账号 复制格式
11.12.14.29 主库 repl Row-Based
11.12.14.30 从库(半同步) repl Row-Based
11.12.14.31 从库(异步) repl Row-Based

通过前面的介绍我们知道MySQL的复制有两种方法

  • 基于二进制日志文件位置
  • 基于GTID

前面已经介绍了第一种这节开始讲关于GTID的内容

1. GTID介绍

GTID是MySQL数据库每次提交事务后生成的一个全局事务标识符,GTID不仅在本服务器上是唯一的,其在复制拓扑中也是唯一的

每当一个客户端事务在服务端提交,该事务会被写入二进制文件同时会被分配一个新的GTID

同时保证每个GTID之间是连续的,不会有GAP

如果客户端事务没有被写入二进制文件(如事务被过滤出去或者是只读的),则不会被分配GTID

GTID的auto-skip特性意味着在主库上执行过的事务不会在从库上执行超过一次

如果一个GTID被提交了,任何相同的GTID的执行请求会被忽略,并且不会报错

如果一个GTID的事务执行了,但没有被提交或回滚,则任何相同GTID的事务会被阻塞,如果这时事务回滚了,则会执行该事务,如提交了则跳过该事务

2. GTID格式

GTID的表现形式如下面

GTID = source_id:transaction_id

其中source_id一般为数据库的uuid,transaction_id为事务ID,从1开始

3E11FA47-71CA-11E1-9E33-C80AA9429562:23

如上面的GTID可以看出该事务为UUID为3E11FA47-71CA-11E1-9E33-C80AA9429562的数据库的23号事务

3.GTID Set

GTID集合为多个单GTID和一个范围内GTID的集合,他主要用于如下地方

  • gtid_executed 系统变量

  • gtid_purged系统变量

  • GTID_SUBSET() 和 GTID_SUBTRACT()函数

他的格式如下

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5

它代表uuid为3E11FA47-71CA-11E1-9E33-C80AA9429562的服务器的1到5号事务

它也可是如下格式

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:11:47-49

他代表该服务器的1到3号,11号和47到49号事务

接下来我们看如下的一个GTID set,他是一个从库的gtid_executed变量的值

2174B383-5441-11E8-B90A-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19

它代表该从库应用了2个库的事务,分别为1到3号事务和1到19号事务

其中uuid是按字母排序的,ID是按数字从小到大排序的

4. mysql.gtid_executed表

接下来我们说下gtid_executed表,它位于MySQL的mysql数据库中

1.png

该表使得从库可以在不开启二进制日志的时候仍然可以使用GTID来进行复制以及在二进制日志文件丢失时获得GTID的状态,他会被reset master命令重置

但需要注意的是复制环境中主库必须要开启二进制日志

只有当gtid_mode为ON 或 ON_PERMISSIVE时才会将执行过的gtid写到gtid_executed表中

当二进制日志开启时,每当日志文件轮转或数据库关闭时,服务器才会将日志中的GTID写到gtid_executed表中

如果数据库发生异常时,服务器会在做恢复时将二进制文件中的gtid写到gtid_excuted表中

5. gtid_executed表和gtid_executed系统变量的区别

从上面我们得知当二进制文件被启用时,gtid_executed表保存的并不是全部的被执行过的gtid,这时我们需要查询gtid_executed 系统变量,他会在每次事务提交后更新

select  @@GLOBAL.gtid_executed
2.png
3.png

可以看出两者不一致,我们刷新下日志后会发现是相同了

4.png

6. gtid_executed表压缩

由于该表会记录每次的提交事务,久而久之会变的非常大,这时服务器会定时的将一些各个GTID合并成一个GTID Set

5.png
6.png

频率由gtid_executed_compression_period系统变量决定,默认值为1000,代表每有1000个GTID会压缩一次,将其设置为0代表禁用该功能

它由thread/sql/compress_gtid_table前台进程完成,并不会出现在SHOW PROCESSLIST 命令中,可以查询下表

7.png

7. 参考资料

本专题内容翻译自官方文档并结合自己的环境

https://dev.mysql.com/doc/refman/5.7/en/replication-gtids-concepts.html