## 实验环境


此次实验的环境如下

- 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的生命周期,提到了gtid_next系统变量,当备库接收到主库的GTID事务后,会将gtid_next变量设为该GTID作为下一个需要执行的事务

接下来具体说下这个系统变量


## 1. gtid_next 

我们知道一个新的事务在提交后会被分配一个新的GTID,当该事务在从库上被应用时会保留主库上的GTID


[image:654 size:orig]




我们可以通过设定gtid_next 的值来改变这种行为


- 1.1 AUTOMATIC

     当设置为AUTOMATIC时(默认值)时,系统会自动分配一个GTID,如果事务回滚或者没有写入到二进制文件时则不会分配



- 1.2  具体的GTID值

    我们可以设置该变量为一个具体的有效的GTID,这时服务器会将该GTID分配给下一个事务,就算该事务没有被写入二进制日志或者为空事务,该GTID也会被分配并加入到gtid_executed变量中

这里需要注意的是,如果该变量值不为AUTOMATIC,我们需要手动的为每个事务指定GTID,否则该事务会失败,你可以将其改为AUTOMATIC,让服务器自动分配,具体可看下面的实验


## 2. gtid_purged 

在gtid_purged系统变量里面的GTID集合是那些已经在服务器上提交的,但已经不存在与二进制日志文件中了

[image:655 size:orig]

gtid_purged 是gtid_executed的一个子集

存在于该变量里面的GTID主要有如下种类

- 从库如果禁用二进制日志功能的话,提交的事务会被记录进去

- 该事务所在的二进制日志文件被清理,可能是人为清理的也可能是自动清理的,自动清理由expire_logs_days参数控制

- 通过设置GLOBAL.gtid_purged变量手动添加进去的,gtid_purged的值,则该GTID也会被写入到gtid_executed变量里面,即不会被执行,注意只有当gtid_executed为空时才可以手动添加


### 2.1 mysqldump中的gtid_purged


还记得在mysqldump专题中讲到需要加上--set-gtid-purged=off参数吗,如果不加上的话会在文件中出现set gtid_purged信息


[image:661 size:orig]



如果这时候用他来还原的话,如果需要还原的库gtid_executed有信息的话是会还原失败的


[image:662 size:orig]


这时可以通过reset master清除掉gtid_executed信息即可




### 3. 关于gtid_next的实验

这个实验我们模拟手工设置gtid_next的值,注意该变量是会话级别的

首先查看现在的执行过的GTID值

[image:656 size:orig]


之后手动设置,首先我们设置为已经执行过的GTID

```
SET @@SESSION.GTID_NEXT= 'e99ae99a-811d-11e9-9ca2-0050568cef02:9';
```

会发现执行成功了,但是并没有新增,说明相同的GTID会被忽略

[image:657 size:orig]

这时我们讲其设为未执行过的GTID,这里我们跳过10和11两个编号

```
SET @@SESSION.GTID_NEXT= 'e99ae99a-811d-11e9-9ca2-0050568cef02:12;
```

[image:658 size:orig]

会发现执行成功并且新增了一行

而且gtid_executed显示的GTID集为1-9:12,有GAP

接下来我们我们试试不设置gtid_next的值看能不能执行成功

[image:659 size:orig]

会发现报错了,说明我们需要手动设置

最后我们讲值设为自动的

```
SET @@SESSION.GTID_NEXT='AUTOMATIC';
```
之后插入几行,发现GTID的GAP补回来了

[image:660 size:orig]



## 4. 参考资料

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

[https://dev.mysql.com/doc/refman/5.7/en/replication-gtids-lifecycle.html](https://dev.mysql.com/doc/refman/5.7/en/replication-gtids-lifecycle.html)