1.MySQL-5.6.2开始支持,MySQL-5.6.10后完善,GTID 分成两部分(uuid:trans_id),一部分是服务的UUid,UUID保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。另外一部分就是事务ID了,随着事务的增加,值一次递增,如下
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+--------------------------------------------+
| binlog.000016 | 1562 | | | ad3690ff-bc92-11e8-b175-005056ae0385:1-45 |
+---------------+----------+--------------+------------------+--------------------------------------------+
GTID:ad3690ff-bc92-11e8-b175-005056ae0385:1-45
UUID:ad3690ff-bc92-11e8-b175-005056ae0385
transactionId:1-362
2.如果复制结构中,直接冷备份,那么主从中的auto.cnf内容是一致的。在启动复制功能的时候会报错。可以删除auto.cnf,然后重启mysql。
1.master更新数据的时候,会在事务前产生GTID,一同记录到binlog日志中。
2.slave端的io线程将binlog写入到本地relay log中。
3.然后SQL线程从relay log中读取GTID,设置gtid_next的值为该gtid,然后对比slave端的binlog是否有记录
4.如果有记录的话,说明该GTID的事务已经运行,slave会忽略
5.如果没有记录的话,slave就会执行该GTID对应的事务,并记录到binlog中
gtid在master和slave上持久化保存,即使删除了日志,也会记录到previous_gtid中。
1.binlog文件中记录的格式是先记录gtid,然后再记录事务相关的操作。
2.gtid_next 是基于会话的,不同会话的gtid_next不同。
3.如果mysql是5.6版本,那么主从必须开启log_slave_updates参数,此时slave对比自己的binlog查看是否有记录。如果mysql是5.7版本,那么主从不需要开启此参数(级联主从除外),mysql5.7提供了gtid_excuted系统表来记录复制的信息,以此减少从库的压力。
例如"gtid_executed 5ad9cb8e-2092-11e7-ac95-000c29bf823d:1-6",表示该server_uuid上执行了从1到6的事务。
4. 5.6版本,slave在应用relay log的时候不是提交后才将gtid写入到自己的binlog中,而是判断gtid不存在后立即写入binlog。通过这种在执行事务前先检查gtid并写gtid到binlog中的机制,可以保证没有其他会话读取了该gtid却没有提交而导致事务重复执行的情况。
如果当前会话读取了该gtid,并将该gtid立即写入binlog(不管是否已经执行该事务),那么其他会话总能读取到binlog中的该gtid,然后其他会话就会放弃该事务。总之,一个事务是不允许多个会话并行执行或多次执行的。
5.slave在应用relaylog的时产生的binlog中的gtid是master的gtid,所以在整个复制架构中GTID是不变的,即使在多个连环主从中也不会变。例如:
ServerA --->ServerB ---->ServerC
GTID从在ServerA ,ServerB,ServerC 中都是一样的。
1.一个事务对应唯一一个ID,一个GTID对应的事务在同一台服务器上只能执行一次。
2.GTID复制与普通复制最大的区别就是 不需要指定二进制文件名和位置
3.当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中;binlog中先记录gtid,紧跟着再记录事务相关的操作。
4.MySQL提供了选项可以控制跳过某些gtid事务,防止slave第一次启动复制时执master上的所有事务而导致耗时过久。
如何跳过?
mysql> reset master;
mysql> set @@global.gtid_purged='a659234f-6aea-11e8-a361-000c29ed4cf4:1-54';
mysql> change master to master_host='192.168.100.21',master_port=3306,master_auto_position=1;
mysql> start slave;
5.对于row模式和statement模式都可以进行gtid复制,建议使用row模式。
例如:ServerC <-----ServerA ----> ServerB
主机:ServerA
备机:ServerB,ServerC
当主机serverA挂了之后,需要将serverB提升为主机(可以通过MHA实现),serverC连接到serverB上。
此时,serverC先在自己的二进制文件中找到从serverA传过来的最新的GTID,将最新的GTID传给serverB,然后serverB就会从这个GTID的下个GTID开始发送事务给serverC。
这种自我寻找复制位置的模式减少了事务丢失的可能性和故障恢复的时间。
主:
[mysqld]
datadir=/data
socket=/data/mysql.sock
log-bin=/data/master-bin # 必须项
sync-binlog=1 # 建议项
binlog_format=row # 建议项
server-id=100 # 必须项
log-error=/data/error.log
pid-file=/data/mysqld.pid
enforce_gtid_consistency=on # gtid复制需要加上的必须项
gtid_mode=on # gtid复制需要加上的必须项
从:
[mysqld]
datadir=/data
socket=/data/mysql.sock
log-bin=/data/master-slave-bin # mysql 5.6必须项,mysql 5.7非必须项
sync-binlog=1 # 建议项
binlog_format=row # 建议项
relay-log=/data/slave-bin # 必须项
server-id=110 # 必须项
log-error=/data/error.log
pid-file=/data/mysqld.pid
enforce_gtid_consistency=on # 必须项
gtid_mode=on # 必须项
需要注意,master和slave上都有gtid_executed和gtid_purged,它们代表的意义有时候是不同的。