欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

Mysql5.6.21-GTID主从复制

程序员文章站 2022-04-13 23:40:32
...

什么是GTID:GTID(global transaction id)是对于一个已提交事务的编号,并且是一个全局唯一编号。 组成部分: UUID+TID 什么是UUID:Mysql实例的唯一标识。 什么是TID:TID代表了该实例上已经提交的事务数量,随着事务提交单调递增。 例子:6dec6fd5-eb1f-

什么是GTID:GTID(global transaction id)是对于一个已提交事务的编号,并且是一个全局唯一编号。


组成部分: UUID+TID


什么是UUID:Mysql实例的唯一标识。

什么是TID:TID代表了该实例上已经提交的事务数量,随着事务提交单调递增。


例子:6dec6fd5-eb1f-12e4-6532-000c29e336f3:20


GTID功能目的:

1:根据GTID可以知道事务最初是在哪个实例上提交的。

2:GTID的存在方便了复制的故障转移。

在5.6版本前,Replication的Failover操作过程。

Mysql5.6.21-GTID主从复制


当A服务器宕机,业务需要切换到B服务器上。需要将C的复制源改成B服务器。

执行以下命令:

CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS='nnnn'


难点在于,同一个事务在每台机器上的binlog名字和位置都不一样。怎么找到C服务器当前同步停止点,对应服务器B的master_log_file和master_log_pos是什么的时候就称为了难题。这就是MMM,MHA出现的根本原因。


在5.6版本后,Replication的Failover操作过程。

由于同一个事务GTID在所有节点上的值一致。那么根据C服务器当前停止点的GTID就能唯一定位到服务器B的gtid,甚至由于Master_Auto_position功能的出现,我们根本不需要自动GTID的具体值,直接使用

CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION命令可以完成故障转移工作。



GTID搭建

实验环境:3台服务器,A,B,C

Mysql5.6.21-GTID主从复制

A:192.168.112.131

B:192.168.112.132

C:192.168.112.129




一:A服务器:192.168.112.131

1:添加复制账号.

sql>GRANT REPLICATION SLAVE ON *.* TO 'ruser'@'192.168.112.%' IDENTIFIED BY 'rpass';

Mysql5.6.21-GTID主从复制


2:配置文件添加以下信息,启用GTID模式。

vim /data/mysqldata/3306/my.cnf

---------------------------------------

server-id=1

log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=3
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log-events=1
report-host=192.168.112.131

----------------------------------------


3:重启动Mysql服务





二:B服务器:192.168.112.132

1:配置文件添加以下信息,启用GTID模式。

vim /data/mysqldata/3306/my.cnf

server-id=10

log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=3
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log-events=1
report-host=192.168.112.132



2:重启动Mysql服务



3:连接Mysql,建立主从关系。

sql>change master to master_host='192.168.112.131', master_user='ruser',master_password='rpass',master_auto_position=1;

sql>start slave;

sql>show slave status\G


4:查看slvae状态,获取关键参数值:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes



三:测试主从同步

1:A主数据库:

sql> create database testhuang;


2:B从数据库:

sql> show databases;

+-----------------------+
| Database |
+-----------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
| testhuang |
+-----------------------+
5 rows in set (0.00 sec)


3:B从数据库GTID执行状态

sql> show slave status\G

Retrieved_Gtid_Set: 7edc6fd5-e1bf-11e4-8842-000c29e512d6:1
Executed_Gtid_Set: 7edc6fd5-e1bf-11e4-8842-000c29e512d6:1




四:模拟binlog日志文件过期

模拟master-slave运行多时,master服务器的部分binlog因为expire_logs_days过期而被删除,此时需要添加多一台slave数据库。

A:192.168.112.131

B:192.168.112.132


服务器A:

1:查看当前主mysql数据库binlog日志文件,以及GTID。

sql>show master status;

Mysql5.6.21-GTID主从复制



2:模拟添加数据,切换binlog日志。

sql>flush logs;

Mysql5.6.21-GTID主从复制Mysql5.6.21-GTID主从复制



3:查看binlog日志位置,GTID位置。

Mysql5.6.21-GTID主从复制



4:手动清除binlog,模拟binlog过期被清除,这里清除06之前的文件,就是说,t1-t4表的日志会丢失。

sql>purge binary logs to 'mysql-bin.000006';



5:可以通过gitd_purge状态参数看到,GTID被清除的事务序号1-5。

sql>show global variables like '%gtid%';

Mysql5.6.21-GTID主从复制Mysql5.6.21-GTID主从复制

在数据库B-slave中,是可以发现t1-t6表的存在,因为已经同步过去了。我们再新增加slave-C的时候,就会发现C无法读取binlog日志而报错。可以通过跳过的方式解决。这样的话就会造成数据库binlog不存在的数据丢失,这个也没办法修复的。因为主从原理就是这样,只能是通过备份/还原的方式去重建。




五:GTID-跳过被清除的事务。

A:192.168.112.131

B:192.168.112.132

C:192.168.112.129


安装mysql参考之前的文章,数据库C添加GTID重要参数。重启动mysql,连接主库-A。


1:修改配置文件,添加以下内容。

vim /data/mysqldata/3306/my.cnf

server-id=12

log-slave-updates=true
gtid-mode=on
enforce-gtid-consistency=true
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=3
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log-events=1
report-host=192.168.112.129


2:重启动mysql服务



3:连接主数据库,知道GTID的好处了吧。

sql>change master to master_host='192.168.112.131', master_user='ruser',master_password='rpass',master_auto_position=1;

sql>start slave;

sql>show slave status\G;

观察报错字段:

Slave_IO_Running: No
Slave_SQL_Running: Yes

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has

purged binary logs containing GTIDs that the slave requires.'


IO错误:读取主的二进制日志致命错误1236,备库请求的GTID的事务内容被清除。



4:跳过被清除的GTID事务。

刚才我们再主库上通过gtid_pirged状态参数查看到1-5的二进制日志文件已经丢失。那么我们跳过该事务。

sql>stop slave;

sql>reset master;

sql>set global gtid_purged = '7edc6fd5-e1bf-11e4-8842-000c29e512d6:1-5';

sql>start slave

不知道我们是否发现,虽然跳过了1-5的事务,但是实际testhuang数据库还是没有创建的,如果跳过的该事务,肯定还会报错。报错没有找到testhuang数据库。



查看slave状态参数:sql>showslave status\G

Slave_IO_Running: Yes
Slave_SQL_Running: No

Last_SQL_Error: Worker 2 failed executing transaction '' at master log mysql-bin.000006, end_log_pos 346; Error 'Unknown database 'testhuang'' on query. Default database: 'testhuang'. Query: 'create table t5(id int)'

Retrieved_Gtid_Set: 7edc6fd5-e1bf-11e4-8842-000c29e512d6:6-7

Executed_Gtid_Set: 7edc6fd5-e1bf-11e4-8842-000c29e512d6:1-5

可以看到,IO线程正常了,但是sql线程异常,确实提示是没有找到testhuang数据库。

在看看后面两个参数,先解释一下:

Retrieved_Gtid_Set:记录了relay日志从Master获取了binlog日志的位置,没错吧,只能拿到事务6-7的日志了。

Executed_Gtid_Set:记录本机执行的binlog日志位置(如果是从机,包括Master的binlog日志位置和slave本身的binlog日志位置)可以从Last_SQL_Error看到创建t5失败。所以这里还是执行1-5,等于没执行。。



5:手动建立testhuang数据库,重新执行跳过事务。

sql>create database testhuang;

sql>stop slave;

sql>reset master;

sql>set global gtid_purged = '7edc6fd5-e1bf-11e4-8842-000c29e512d6:1-5';

sql>start slave

下图是我拼起来的,观察几个重要的参数就可以了

sql>show slave status\G

Mysql5.6.21-GTID主从复制

呵呵,slave3 建立起来了,虽然数据丢失了,不是我们想要的结果,没办法,日志都没了,怎么复制,不然就违背mysql的复制原理了,但不可否认,是不是符合前面说的,同一个事务所有GTID都是一致的。





六:GTID-完整Slave创建。

A:192.168.112.131

B:192.168.112.132

C:192.168.112.129

还是拿服务器C来做完全恢复,来个最干净的环境,把上面的数据库初始化。


前面说过日志文件丢失了,就没办法做恢复了,我们可以把数据备份出来,然后导入到C服务器上,再进行主从数据同步。考虑到A是主库,生产部建议在主库上做备份。因为这里的备份考虑到数据的一致性,我们需要先把表都锁起来。禁止写入,但是生产啊,怎么能这样做呢,,只要锁从库-B了。。



1:B库,锁表,禁止写入数据。

记住,一定要停止主从关系后锁表,哈哈,主从都停止了,还有数据写入么。。停止了直接被备份就好了。。。

sql> stop slave;

sql> flush tables with read lock;

Mysql5.6.21-GTID主从复制




2:模拟主库现在又有数据写入了。。。。有真实感了没有?

A库:插入几行数据。

sql>flush logs;

sql>create table t7(id int);

sql>create table t8(id int);

sql>flush logs;

sql>create table t9(id int);

sql>create table t10(id int);



3:备份B库。全备?单库备,任你选,但是恢复的方式不一样。因为全备会把GTID信息备份过去,单库备份还原的话不会。

全备:

$ mysqldump -umysql-admin -p --all-databases > all.sql

Enter password:
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events.

发现报错,不过是Warning,说的就是导出GTID,默认情况下导出所有事务,如果你不是用来做slave,就添加--set-gtid-purged=OFF。一个完整的转储, --all-databases --triggers --routines --events。



这样执行就不爆Warning了。

$mysqldump -umysql-admin -p --all-databases --triggers --routines --events --set-gtid-purged=ON > all.sql



4:释放从库B锁,启动slave线程

sql>unlock tables;

sql>start slave;



5:导入数据库C。

$ /usr/local/mysql56/bin/mysql -umysql-admin -p

Mysql5.6.21-GTID主从复制

报错了,就是说要开启GTID。因为C库是刚初始化的,还没有在my.cnf里面添加GTID参数,添加完后,重起mysql,再次导入。



添加GTID参数后,重启动mysql,再次导入。

$ /usr/local/mysql56/bin/mysql -umysql-admin -p

Mysql5.6.21-GTID主从复制

大功告成。。。。




6:重建立主从关系。

先查看几个表数据的情况。

sql>show databases;

sql>use testuhang;

sql>show tables;

Mysql5.6.21-GTID主从复制

可以看到t1-t6表就对了。锁表前,就是写到t6。



sql>show master status;

Mysql5.6.21-GTID主从复制

看看GTID事务,,数据非常吻合。因为备份的时候,刚好执行了7个事务。



连接主数据库。

sql>change master to master_host='192.168.112.131', master_user='ruser',master_password='rpass',master_auto_position=1;



如果看到以下结果,恭喜你。恢复成功。

Mysql5.6.21-GTID主从复制



sql>show slave status\G

Mysql5.6.21-GTID主从复制

可以看到retrieved_Gtid_Set的值是8-11,因为1-7的事务是通过恢复出来的,并不是从主库拉取过来的。