参考: https://www.cnblogs.com/leohahah/p/11533952.html
GTID生命周期:
1, 如果实例启用了GTID,当提交事物的时候,系统自动分配一个GITD,
GTID = uuid:transaction_id
uuid:每个实例都有一个唯一的uuid,查看方法: select uuid();
transaction_id: 通常为自增序列,第一个是1,往后递增;如:bb08f12d-b9c4-11e9-8916-fa162e6b02e2:405832
a23c850c-b9c7-11e9-b8e0-fa16f381d97a:1-1975,这种表示1-1975这个范围内的这么多GTID;
2, 当事物提交后,它会被加入到@@GLOBAL.gtid_executed参数中; @@GLOBAL.gtid_executed表示该实例执行过的所有GTID记录范围;
mysql> select @@global.gtid_executed\G
*************************** 1. row ***************************
@@global.gtid_executed: 70a76530-b9d3-11e9-8d38-fa16bae5f8ca:1-1070,
a23c850c-b9c7-11e9-b8e0-fa16f381d97a:1-1975,
bb08f12d-b9c4-11e9-8916-fa162e6b02e2:1-405834
1 row in set (0.00 sec)
当主从首次同步的时候(master_auto_position=1),从库将@@GLOBAL.gtid_executed列表发送给主库,主库核对GTID列表,并从首个未执行的BINLOG发送给从库执行同步任务;
3, 当BINLOG被发送给SALVE, SLAVE的IO线程会把该会话的gtid_next参数设置为该GTID, 注意这里的gtid_next是复制线程的session中设置的, 而用户查看的时候查看的是用户会话的gtid_next; 看到的结果是默认的AUTOMATIC;
4, 如果开启了并行复制,SALVE会读取并检查GTID,对比@@GLOBAL.gtid_executed确保该GTID未被执行过; 如果有并行复制进程在应用该事物,那么SLAVE直运行一个进程继续执行; @@GLOBAL.gtid_owned 展示了哪个并行进程在执行什么事物;
5, 如果SLAVE开启了BINLOG,从库也会记录该事物的GTID(同MASTER的GTID);且实例重启后会同样被同步到mysql.gtid_executed中;
mysql.gtid_executed表主从可能会不一致,都是记录本实例已执行过的GTID列表;
番外:
a, 当实例重启或者切换的时候,GTID信息会被更新到mysql.gtid_executed表中,用于持久化;
如:
mysql> select * from mysql.gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 70a76530-b9d3-11e9-8d38-fa16bae5f8ca | 1 | 1070 |
| a23c850c-b9c7-11e9-b8e0-fa16f381d97a | 1 | 1975 |
| bb08f12d-b9c4-11e9-8916-fa162e6b02e2 | 1 | 405833 |
+--------------------------------------+----------------+--------------+
b, 如果BINLOG被删除,则删除部分的GTID信息会被更新到@@GLOBAL.GTID_PURGED中;
mysql> select @@global.gtid_purged\G
*************************** 1. row ***************************
@@global.gtid_purged: 70a76530-b9d3-11e9-8d38-fa16bae5f8ca:1-1070,
a23c850c-b9c7-11e9-b8e0-fa16f381d97a:1-1975,
bb08f12d-b9c4-11e9-8916-fa162e6b02e2:1-405831
1 row in set (0.00 sec)
注意:1, @@GLOBAL.GTID_PURGED是 @@GLOBAL.gtid_executed的子集;
2,如果SLAVE上未启用BINLOG,则@@GLOBAL.GTID_PURGED == @@GLOBAL.gtid_executed
3, 如果要手动SET @@GLOBAL.GTID_PURGED,前提是@@GLOBAL.gtid_executed为空; 要@@GLOBAL.gtid_executed为空命令为:reset master;
4, 如果主从异常,且主库的BINLOG已经丢失,可以修改@@GLOBAL.GTID_PURGED到有BINLOG的位置,待主从同步后再进行数据校验来修复数据;
c, gtid跳过事物的方法:
stop slave;set gtid_next='要跳过的事务GTID';begin;commit;set gtid_next=AUTOMATIC;start slave;
d, GTID并非只会被分配给事务,一个事务也可能会被分配多个GTID。
e, MySQL5.7.7版本之前 gtid_executed和gtid_purged的值可能会错误的生成,此时需要将 binlog_gtid_simple_recovery 设为FALSE,然后重启实例,它会在遍历BINLOG重新计算生成GTID;因此推荐在mysql5.7.8之后的版本上启用GTID复制
f, reset master会清除: @@global.gtid_purged, @@global.gtid_executed, mysql.gtid_executed, 清理binlog;
g, reset slave和reset slave all; 都会清理掉@@global.gtid_executed和@@global.gtid_purged