MySQL主从复制(4)GTID主从复制与运维管理教程

Tanglu MySQL 2021-03-15 6418 0

一、GTID特性介绍

1、MySQL 5.6开始支持GTID全局事务标识,在5.7之后即便没有配置GTID也会存在匿名事务,只不过这个匿名事务不包含GTID信息,不能用于主从复制

2、GTID拥有全局唯一、幂等性,一个完整的GTID包含了UUID和GTID两部分。UUID即Server_uuid,用于区分事务来自于集群中哪个节点,MySQL在启动的时候通过读取auto.cnf获取UUID,如果auto.cnf文件丢失则会自动生成新的UUID

#对于来自同一个实例的事务GTID会进行合并,比如来自同一个实例的1-3个事务会写为1-3
2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-3

#来自同一个实例的1-3个事务,第11个事务,第48-51个事务
2a09ee6e-645d-11e7-a96c-000c2953a1cb:1-3,11,48-51

3、GTID是每个事务的全局唯一编号,每当有事务导致数据变化,GTID末位的数字就会自增

4、每一个DDL都有一个GTID,对于DML语句,从begin开始到commit结束才算一个GTID

5、如果普通的主从架构下GTID发生了空洞(比如1-100,200-300这样不连续的事务)需要检查主从数据是否完全一致,但在MGR场景下空洞是正常的

6、因为全局唯一性,GTID可以简化主从复制的维护,配置主从不再需要手动指定Position信息,只需要告知从库当前从哪个GTID开始执行后面的事务即可。这个特点对于主从切换也更方便,配置GTID后不同节点之间的GTID是连续的,而传统模式下每个节点的binlog信息则会不同,一旦发生主从切换,由于从库记录的position信息是原主库的,而切换新主库后binlog信息是完全不一致,没办法直接指定正确的position

7、GTID不再支持create table...select...语句,因为该语句实际是先CREATE TABLE再INSERT会生成2个GTID,违背了GTID下一个事务只有一个GTID的特性

8、不支持CREATE TEMPORARY TABLE临时表相关操作


二、GTID相关表与变量

· mysql.gtid_executed表用于持久化存储GTID信息,数据库实例启动时会读取该表信息并赋值给gtid_executed变量。在MySQL 5.6时期是使用binlog中的GTID_LOG_EVENT来持久化GTID信息的,所以必须配置log_slave_updates=1

· gtid_executed变量表示当前数据库执行过的GTID集合,gtid_executed变量一定是实时更新的。执行show master status或show slave status命令时Executed_Gtid_Set的值就来自于该变量

· gtid_purged变量如果Binlog因为过期或人为操作被删除,其中包含的GTID信息将记录于此。在部署从库的时候通常需要使用set global gtid_purged设置本变量,表示从库不需要再执行这些GTID包含的操作,否则会因为日志被删除了而导致同步失败


三、GTID主从部署(GTID依赖于事务,所以MySQL必须配置为InnoDB引擎才可以

1、在所有节点新增GTID相关配置,MySQL 5.7开始支持在线配置GTID,无需重启服务。但是为了确保MySQL能正确处理从匿名事务更改为GTID事务的过程,gtid_mode的值只能按照顺序逐一提升或下降,如可以从OFF_PERMISSIVE逐步升级为ON_PERMISSIVE和OFF,但是不能直接调整为ON,关于GTID在线开启详见https://www.linuxe.cn/post-647.html

gtid_mode = on  #开启GTID
enforce_gtid_consistency = on  #强制GTID一致性,开启后如果再去执行一些会导致GTID复制失败的语句会报错,可以避免数据的不一致
#log_slave_updates = 1  #5.7以后通过gtid_executed表对GTID持久化,所以可以不配置该参数,5.6则依赖binlog进行持久化,所以必须开启


2、主库进行授权操作

grant replication slave,replication client on *.* to 'repl'@'192.168.1.110' identified by '123456'


3、从库恢复主库的全备数据,恢复后需要指定gtid_purged变量信息,这个信息根据备份方式不同查找的路径会有一些不同。如果是mysqldump逻辑备份,在备份文件前50行会有gtid_purged变量,而xtrabackup物理备份的话则会写入到xtrabackup的备份文件中

show master status \G  #备份完成后通过该命令可以看到从节点和主节点GTID信息是一致的 
reset master;  #防止从库读取到错误的gtid_executed变量,执行该命令可以重置变量
set global gtid_purged='xxxxxxxxxx:1-21';


4、指定同步位点信息。由于采用了GTID,所以从库在指定position信息时只用声明从哪个GTID后开始同步即可

change master to master_host='192.168.1.100',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;
start slave;


5、数据目录下的auto.cnf存放了当前数据库的UUID,每个节点的ID是不能一样的,如果一样会出现主从状态是2个yes,但是数据不同步的情况

show global variables like 'server_uuid' ;


6、主库执行show binlog event命令可以查看当前事务情况,SET开头的行是GTID,下面一行就是具体的SQL

GTID.png


7、在从库执行show slave status命令查看事务ID是否与主库一致,Retrieved_Gtid_Set表示从库已经接受到的GTID信息;Executed_Gtid_Set表示从库已经应用了的GTID信息

企业微信截图_20181010095354.png


8、采用了GTID复制后从库也会产生binlog日志,通过show master logs可以看到与主库是一致的。在从库执行show binlog event in 'master-bin.000001'命令可以查看当前所执行的事务ID位置,正常情况与主库也是一致的


四、GTID模式下数据恢复

1、在gtid模式下需要进行数据恢复,第一步也是从binlog找出正确的gtid信息然后导出,解析binlog的过程这里略过,假设已经定位到GTID 101的事务是属于drop table,那么就需要恢复到101之前的最后一个事务,假设为100

mysqlbinlog --include-gtids='yourgtid:1-100' mysql-bin.00001 mysql-bin.00002 mysql-bin.00003 mysql-bin.00004 > /tmp/gtid.sql
#还有--exclude-gtids选项用于排除某个GTID


2、使用mysqlbinlog进行恢复的时候要注意,由于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;


五、GTID模式下如何跳过事务

1、和传统主从不同,开启GTID后如果需要跳过一个事务不能再使用sql_slave_skip_counter参数,而是要获得从库执行的最后一个GTID操作。也就是show slave status 中的Retrieved_Gtid_Set信息。企业微信截图_20211008171159.png


2、构建一个或多个空事务

stop slave;
set gtid_next='xxxxxxxxxxxxxxxcb140c:10903292'
begin;
commit;

set gtid_next='xxxxxxxxxx3:4'
begin;
commit;

set gtid_next='automatic';
start slave;


六、GTID模式下的常见故障

· Master_has_purged_require_gtids

主库提前删除了还未同步完成的binlog

#在从库上手动指定二进制日志文件和位置
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;


· 如果从库未指定relaylog的同时修改了系统主机名,只需要在从库重新执行一次同步

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;


· Slave has more GTIDs than the master has,using the master's SERVER_UUID

该问题代表从库获取到的GTID超过了主库,比如主库在未指定binlog文件名的同时修改了系统主机名,导致binlog全部被修改,从库就会判断失败;或者主库未配置双1参数时断电,导致从库提前获取到了还未执行的GTID,解决方法如下:

#全在从库执行
stop slave;
reset slave;
reset master;  #从库的binlog已经无效了,所以要执行这个命令清空binlog
change master to master_host='192.168.1.100',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;


评论