一、什么是GTID
MySQL在5.6版本开始支持GTID,也就是全局事务标识(阿里云的RDS就使用到GTID)。5.7即便不配置也会有一个匿名GTID记录。GTID由每个MySQL节点自身的唯一UUID+每个事务产生的事务ID构成,每当数据发生变化时GTID末位的数字会自增,这个ID是全局唯一且具有幂等性的,也就是说每个事务都有一个全局唯一的编号。
在MySQL中每个DDL都会有一个GTID,而对于DML来说则是从begin开始到commit才算一个GTID。使用GTID配置主从不再需要手动指定Position信息了,只需要告知从库当前GTID的编号即可,剩下就由服务自己来执行那些没有发生过的事务。从库还可以并行接收多个事务,只需要根据GTID序号依次处理就可以了,并发性能也得到了提升。
需要注意的是GTID复制依赖于事务,所以MySQL必须配置为InnoDB引擎才可以。GTID模式下主从复制流程:从库通过IO进程把主库binlog传输到本地relaylog,然后查看relaylog中的GTID是否已经存在,已经存在则不执行。而且在不同的binlog文件中GTID都是连续的,不需要在每个binlog中去寻找position。
二、GTID主从部署
1、在原有的数据库文件配置上新增GTID相关配置,这些配置需要在所有节点上都有
gtid_mode = on #开启GTID
enforce_gtid_consistency = on #强制GTID的一致性
log-slave-updates = 1 #MySQL 5.6版本必须开启这个,5.7已经可以不用,但建议打开
2、主库进行授权操作
grant replication slave,replication client on *.* to 'repl'@'192.168.1.110' identified by '123456'
3、从库在指定主库信息时不再需要position,而是根据GTID去自动判断哪些操作需要同步。主库的position信息会自动写到从库数据目录下的master.info文件中
change master to master_host='192.168.1.100',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;
start slave;
4、数据目录下的auto.cnf存放了当前数据库的UUID,每个节点的ID是不能一样的,如果一样会出现主从状态是2个yes,但是数据不同步的情况)
show global variables like 'server_uuid' ;
5、主库执行show binlog event命令可以查看当前事务情况,SET开头的行是GTID,下面一行就是具体的SQL
6、在从库执行show slave status命令查看事务ID是否与主库一致
7、采用了GTID复制后从库也会产生binlog日志,通过show master logs可以看到与主库是一致的。在从库执行show binlog event in 'master-bin.000001'命令可以查看当前所执行的事务ID位置,正常情况与主库也是一致的
三、使用GTID进行数据恢复
1、如果在gtid模式下需要进行数据恢复,第一步也是从binlog找出正确的位置信息,然后导出
mysqlbinlog --include-gtids='yourgtid:1-100' mysql-bin.00001 mysql-bin.00002 mysql-bin.00003 mysql-bin.00004 > /tmp/gtid.sql #假设101的GTID为drop table,就截取到100即可
#还有--exclude-gtids选项用于排除某个GTID
2、由于GTID有幂等性,相同的GTID不会再次执行,所以恢复的时候要手动关闭GTID检查,或者在mysqlbinlog中加入--skip-gtids的选项,它会将重定向文件中的GTID信息删除掉
#方法1
mysqlbinlog --skip-gtids include-gtids='xxxxxxxxxxx:1-100' mysql-bin.00001 mysql-bin.00002 > /tmp/gtid.sql
#方法2
mysql > set sql_log_bin = 0 ;
mysql > source gtid.sql;
四、Binlog主从模式转GTID模式
1、
2、
五、GTID主从复制发生异常如何处理
1、当主服务器发生意外情况导致从库无法自动同步时的解决(如从库停机期间主库的二进制日志被删除,会导致从库无法找到需要的ID):
#在从库上手动指定二进制日志文件和位置
mysql > stop slave;
mysql > change master to master_host='192.168.1.100',master_user='repl',master_password='123456',master_log_file='master-bin.000005',master_log_pos=526,master_auto_position=0;
mysql > start slave;
2、如果从库忘了指定relay-log而又发生了主机名更改的情况,只需要在从库重新执行一次同步
stop slave;
reset slave;
change master to master_host='192.168.1.100',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;
3、如果主库忘了指定bin-log而又发生了主机名更改的情况,从库会报错“Slave has more GTIDs than the master has,using the master's SERVER_UUID”,意思就是说自己的GTID比主库的更大了。解决方法(所有命令在从库执行):
stop slave;
reset slave;
reset master; #从库的binlog已经无效了,所以要执行这个命令
change master to master_host='192.168.1.100',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;