Mysql GTID主从复制故障后不停机恢复同步流程

Mysql GTID主从复制长时间故障后不停机恢复同步流程

模拟之前先来简单学习一下GTID的知识。
1. GTID的基本概念

GTID的全称为全局事务标识符(global transaction identifiner),是MySQL 5.6引入的一个特性。
GTID保证了MySQL的每一个事务都有一个全局唯一的标识,该标识在本实例甚至主从复制环境都保证全局唯一。

GTID = server_uuid:sequence_id
server_uuid是一个32字节+1字节(/0)的字符串,MySQL第一次启动时生成,并将该信息写入datadir目录下
的auto.cnf文件。如果该文件丢失,MySQL会重新生成一个新的server_uuid。相同的server_uuid下的事务
对应的sequence_id在binlog文件中是递增且连续有序的,他们以集合的方式呈现。
GTID = server_uuid:sequence_id   GTID号示例:

Mysql GTID主从复制故障后不停机恢复同步流程_第1张图片

2. GTID的优点

1 通过gtid定位该事务来自哪个实例。

2 搭建主从复制不再需要指定binlog文件以及具体的位点信息,而是通过全局唯一的gtid来做复制,MySQL通
过gtid来验证冲突并确保每个事务只会被执行一次。

3实现主从更简单,不用像以前一样寻找log_file和log_pos,而是使用 master_auto_position=1 的方
式自动匹配 GTID 断点进行复制。

4 比传统的主从更加安全,一个 GTID 在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。

5 GTID是连续没有空洞的,保证数据一致性。

3. GTID生命周期  以Mysql5.7为例

1 当事务于主库执行时,系统会为事务分配一个GTID,(当然读事务或者被主动过滤掉的事务不会被分配GTID)
,写binlog日志时,此GTID标志着一个事务的开始。

2 binlog中写GTID的event被称作Gtid_log_event,当binlog切换或者mysql服务关闭时,之前binlog中
的所有gtid都会被加入mysql.gtid_executed表中。

3 当GTID被分配且事务被提交后,他会被迅速的以一种外部的、非原子性的方式加入 @@GLOBAL.gtid_executed 
参数中,这个参数包含了所有被提交的GTID事务(其实他是一个GTID范围值),这个参数也被用于主从复制,
表示数据库当前已经执行到了哪个事务。

4 在主从首次同步时(master_auto_position=1),slave会通过gtid协议将自己已经执行的gtid set
(@@global.gtid_executed)发给master,master比较后从首个未被执行的GTID事务开始主从同步。

5 当事务随binlog被传输至slave后,slave每次读到Gtid_log_event就把自己的gtid_next参数设为此
GTID,需要注意的是 这里的gtid_next是在复制进程的session context中自动设置的(由binlog提供的
语句),这里的结果不同于show variables like 'gtid_next';是当前会话本身的gtid_next,
这是个session级别的参数。

6 同样的,在slave上如果开启了binlog,GTID也会以Gtid_log_event事件写入binlog,同时binlog切换
或者mysql服务关闭时,当前binlog中的所有gtid都会被加入mysql.gtid_executed表中。

7 在备库上如果未开启binlog,那么GTID会被直接持久化到mysql.gtid_executed表中,在这种情况下
slave的mysql.gtid_executed表包含了所有已经被执行的事务。需要注意的是在mysql5.7中,向mysql.gtid_executed
表插入GTID的操作与DML操作是原子性的,对于DDL操作则不是,因此如果slave在执行DDL操作的过程中异常中
断那么GTID机制可能会失效。在mysql8.0中这个问题已经得到解决,DDL操作的GTID插入也是原子性的。

4. 主从复制搭建需要关注的参数

server_id            //主从库server-id必须不一样

log_bin             //主库必须打开binlog日志

binlog_format=row      // #bin_log日志格式,共有三种STATEMENT、ROW、MIXED 

gtid_mode=on           //开启gtid

enforce_gtid_consitency=on    //on off WARN  保证gtid一致性

log_slave_updates        //5.6版本中使用gtid必须开启该参数,5.7.5以后该参数决定gtid信息持久化介质是哪些


开始模拟:这里我们模拟一个主从复制架构中,从服务器中途异常宕机,不再同步主服务器的场景,假设该情况
宕机时间较长,数据量较大,GTID无法短时间恢复,并要求不停业务进行数据同步修复,恢复一致。
(或者说主服务器宕机,从服务器代替主服务器提供服务,现在要恢复主服务器的数据,使它与从服务器的数据同步)。
在主服务器中创建从服务器连接的用户

CREATE USER 'copy'@'176.104.XXX.XX' IDENTIFIED BY 'copy';

GRANT REPLICATION SLAVE ON *.* TO 'copy'@'176.104.XXX.XX';

flush privileges;     
使用mysqldump使主从信息一致
主mysql执行:

mysqldump -uroot -p123 demo > dump2.sql 
scp dump2.sql 172.16.104.XX:/
从mysql执行:
mysql> source /dump2.sql

查看主从数据;
Mysql GTID主从复制故障后不停机恢复同步流程_第2张图片
Mysql GTID主从复制故障后不停机恢复同步流程_第3张图片

信息一致,开启主从复制:

CHANGE MASTER TO

 MASTER_HOST='172.104.**.*',

 MASTER_USER='copy',

 MASTER_PASSWORD='copy',

 MASTER_PORT=3306,

 MASTER_AUTO_POSITION=1;  
start slave;
查看从库状态:show slave status\G
IO/SQL线程都为YES,开启成功。

Mysql GTID主从复制故障后不停机恢复同步流程_第4张图片

在主库中添加数据测试,从库也同步到数据,主从一致。

Mysql GTID主从复制故障后不停机恢复同步流程_第5张图片

Mysql GTID主从复制故障后不停机恢复同步流程_第6张图片

编写脚本,设置数据随机插入模拟业务增长。 (插入时间间隔 < 5s), 利用Random函数
运行脚本并挂载到后台:nohup sh insert.sh & 

Mysql GTID主从复制故障后不停机恢复同步流程_第7张图片

查看主从数据:同步,业务模拟完成。

Mysql GTID主从复制故障后不停机恢复同步流程_第8张图片

Mysql GTID主从复制故障后不停机恢复同步流程_第9张图片

此时节点还在陆续插入

Mysql GTID主从复制故障后不停机恢复同步流程_第10张图片

在这里模拟从库宕机(手动stop) 

Mysql GTID主从复制故障后不停机恢复同步流程_第11张图片

从库数据:276rows

Mysql GTID主从复制故障后不停机恢复同步流程_第12张图片

主库数据:294rwos,发现数据不一致。到此模拟主从故障完成。

Mysql GTID主从复制故障后不停机恢复同步流程_第13张图片

开始恢复数据 

思路:
先通过mysqldump全量备份当前的数据,由于不能影响业务,所以在mysqldump数据时不能造成锁表。要保持
数据写入,由于mysqldump时数据还在写入,所以有一部分数据还是会同步不全,所以导入mysqldump的数据
后,跳过dump中包含的GTID事务,再重新建立一次主从配置,开启slave线程,恢复数据并同步。
mysqldump不锁表备份数据

mysqldump -uroot -p123 --single-transaction --master-data=2 -R demo > dump4.sql

主要起作用参数:--single-transaction:设置事务的隔离级别为可重复读,即REPEATABLE READ,这样能保证在一个事务中所有相同的查询读取到同样的数据,也就大概保证了在dump期间,如果其他innodb引擎的线程修改了表的数据并提交,对该dump线程的数据并无影响,在这期间不会锁表。
在从库中导入数据:
scp dump4.sql 172.104.**.*/d
mysql客户端内:
mysql> source /dump4.sql
此时从库中数据:

Mysql GTID主从复制故障后不停机恢复同步流程_第14张图片

主库中数据,可以看出,数据仍然未同步。

Mysql GTID主从复制故障后不停机恢复同步流程_第15张图片

由于我们mysqldump的数据已经包含了在MASTER执行的 1-274 个事务,所以我们在此时SLAVE进行同步的时候,要忽略这些事务不再进行同步,不然会出现类似于这种报错:

Mysql GTID主从复制故障后不停机恢复同步流程_第16张图片

要想跳过某些GTID,SLAVE必须保证 gtid_purged 参数为空才能正确跳过,查看当前的gtid_purged:

Mysql GTID主从复制故障后不停机恢复同步流程_第17张图片

当前gtid_purged不为空,所以我们要先设置它为空,执行:reset master;                   

查看gtid_purged  
mysql> show global variables like '%gtid%';

Mysql GTID主从复制故障后不停机恢复同步流程_第18张图片

reset master实际上做了以下操作:

将gtid_purged参数设为空字符
将gtid_executed设为空字符
清空mysql.gtid_executed表
如果DB server开启了binlog,那么reset master还会清除所有binlog文件和binlog index file,然后以初始的自增序列号1开启一个新的binlog        

Mysql GTID主从复制故障后不停机恢复同步流程_第19张图片

gtid_purged为空后,开始重置SLAVE

mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> reset slave all;
Query OK, 0 rows affected (0.02 sec)
查看主库当前mysqldump导出数据的GTID号

在这里插入图片描述


重置后,设置跳过的GTID,并重新同步MASTER

mysql>SET @@GLOBAL.GTID_PURGED='c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228';
Query OK, 0 rows affected (0.01 sec)
mysql>CHANGE MASTER TO MASTER_HOST='192.168.152.253',MASTER_USER='copy',MASTER_PASSWORD='copy',MASTER_PORT=3306,MASTER_AUTO_POSITION=1;

Query OK, 0 rows affected, 2 warnings (0.04 sec)
开启SLAVE进程,查看同步状态

Mysql GTID主从复制故障后不停机恢复同步流程_第20张图片

状态正常,在看一下数据。

Mysql GTID主从复制故障后不停机恢复同步流程_第21张图片

Mysql GTID主从复制故障后不停机恢复同步流程_第22张图片

在我们修改过程中插入的数据也已经全部同步。数据完全一致,主从复制修复完成。
GTID的限制
1. create table … select其实会转换为两个单独的事务,一个是create table,一个是insert数据。
当在事务中执行该语句时,一些情况下会导致两个事务分配了相同的事务id,这意味着从库会忽略掉插入数据
的事务,从而导致主从数据不一致

2.临时表的限制,只有在acticommit=1的情况下,才支持使用create temporary table和drop temporary 
table语句。Master端创建临时表不产生GTID信息,所以不会同步到slave,但是在删除临时表的时候会产生
GTID会导致,主从中断.

3.主从库存储引擎不一致的情况下,会导致数据不一致

4.事务中包含对多个存储引擎的查询更新,会导致对该事务分配多个gtid

5.sql_slave_skip_counter传统模式的跳过position方式gtid模式下不支持。

你可能感兴趣的:(Mysql,mysql)