Rumah  >  Artikel  >  pangkalan data  >  Mysql5.6.21-GTID主从复制

Mysql5.6.21-GTID主从复制

WBOY
WBOYasal
2016-06-07 14:55:531504semak imbas

什么是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操作过程。

wKioL1Usw4Phsh1-AADedPcz6W4471.jpg


当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

wKioL1Uswz-TnuIdAABYRYdd4ks472.jpg

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'; 

wKioL1UsxEXCw5VyAADvfXb2IMo644.jpg


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;

wKiom1UsxTHyO3IQAAEOUfcqURc376.jpg



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

sql>flush logs;

spacer.gifwKioL1Usxl_RHQcmAAL5hukXAdA615.jpg



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

wKiom1UsxPSgIJY8AAFH_T71p1s553.jpg



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%';

spacer.gifwKiom1UsxMqwYOncAAGPfs9gc2k156.jpg

在数据库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

wKiom1Usxd_yU1QQAAIL8a2lx8Q581.jpg

呵呵,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;

wKiom1UsxoOytL-0AACRqVJZL_Q528.jpg




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

wKiom1UsxmGDptEQAAC0pGzjdNo304.jpg

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



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

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

wKioL1UsyNLBiP07AABs9nvmJ-8730.jpg

大功告成。。。。




6:重建立主从关系。

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

sql>show databases;

sql>use testuhang;

sql>show tables;

wKioL1UsyDHD7XyuAAEZvXb-nZ4383.jpg

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



sql>show master status;

wKiom1UsxvDD4foUAAFEZEKTbDA830.jpg

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



连接主数据库。

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



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

wKioL1UsyKnRZYCLAAMVJ715VgE484.jpg



sql>show slave status\G

wKioL1UsyLWg-Ng-AAHNnwTPOFQ367.jpg

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




Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn