加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

GTID及多源主从复制

(2019-01-22 09:26:38)
分类: mysql主从及监控

 1.GTID的概述

 1、全局事物标识:global transaction identifieds

2GTID事物是全局唯一性的,且一个事务对应一个GTID

3、一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。

4GTID用来代替classic的复制方法,不在使用binlog+pos开启复制。而是使用master_auto_postion=1的方式自动匹配GTID断点进行复制。

5MySQL-5.6.5开始支持的,MySQL-5.6.10后开始完善。

6、在传统的slave端,binlog是不用开启的,但是在GTID中,slave端的binlog是必须开启的,目的是记录执行过的GTID(强制)。

GTID概念:

GTID=source_id:sequence_id

source_id使用服务器的uuid来进行标志

sequence_id系统顺序分配的序列号,连续并且有序.

GTID的便利性:

根据GTID可以快速查看事务在哪个实例上提交的.

根据GTID可以复制更加简单,确保每个事务只能被执行一次.

根据GTID可以更加方便的实现failover,不用再去找master_log_filemaster_log_pos.


 2.GTID的组成部分:

 前面是server_uuid:后面是一个序列号例如:server_uuidsequence number

7800a22c-95ae-11e4-983d-080027de205a:10

UUID:每个mysql实例的唯一ID,由于会传递到slave,所以也可以理解为源ID

Sequence number:在每台MySQL服务器上都是从1开始自增长的序列,一个数值对应一个事务。

 3.GTID比传统复制的优势:

1、更简单的实现failover,不用以前那样在需要找log_filelog_Pos

2、更简单的搭建主从复制。

3、比传统复制更加安全。

4GTID是连续没有空洞的,因此主从库出现数据冲突时,可以用添加空事物的方式进行跳过。(故障转移上有优势)


 4.GTID参数

 gtid_executed:

在当前实例上执行过的GTID集合实际上包含了所有记录到binlog中的事务。所以,设置set sql_log_bin=0后执行的事务不会生成binlog 事件,也不会被记录到gtid_executed中。执行RESET  MASTER可以将该变量置空。

gtid_purged:

binlog不可能永远驻留在服务上,需要定期进行清理(通过expire_logs_days可以控制定期清理间隔),否则迟早它会把磁盘用尽。gtid_purged用于记录已经被清除了的binlog事务集合,它是gtid_executed的子集。只有gtid_executed为空时才能手动设置该变量,此时会同时更新gtid_executed为和gtid_purged相同的值。gtid_executed为空意味着要么之前没有启动过基于GTID的复制,要么执行过RESET  MASTER。执行RESET MASTER时同样也会把gtid_purged置空,即始终保持gtid_purgedgtid_executed的子集。

gtid_next:

会话级变量,指示如何产生下一个GTID。可能的取值如下:

1AUTOMATIC

自动生成下一个GTID,实现上是分配一个当前实例上尚未执行过的序号最小的GTID

2ANONYMOUS

设置后执行事务不会产生GTID

3)显式指定的GTID

可以指定任意形式合法的GTID值,但不能是当前gtid_executed中的已经包含的GTID,否则,下次执行事务时会报错。


 5.从库与主库对应的事务的GTID为什么是相同的?

查看主库binlog里的GTID:发现是set @@global.gtid_purged=....从库的binlog也是一样.

原因从库设置gtidAUTOMATIC,从库执行中继日志时会先执行set @ @ global.gtid_purged =....故两者GTID相同.且会往后传递.

 6.GTID的工作原理:

 1master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。

2slave端的i/o 线程将变更的binlog,写入到本地的relay log中。

3sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。

4、如果有记录,说明该GTID的事务已经执行,slave会忽略。

5、如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog

6slave在接受masterbinlog时,会校验masterGTID是否已经执行过(一个服务器只能执行一次)。

7、为了保证主从数据的一致性,多线程只能同时执行一个GTID


 7.MySQL GTID的开启

 5.6不能在线开启GTID           5.7可以在线开启GTID

修改GTID需要添加的参数:

MySQLMasterSlave必须同时开启或者关闭enforce-gtid-consistencygtid-mode功能,即GTID开关要保持一致。

开启GTID功能,需要同时开启log-binlog_slave_updates功能,另外还需要开启enforce_gtid_consistency功能。

先开启log_bin(只读参数)功能.(show variables like 'log_bin';)

gtid_mode=on    #开启gtid

log_slave_updates=1和 enforce_gtid_consistency=1    #保证gtid的一致性

可以将参数添加到配置文件里:

gtid_mode=on

enforce_gtid_consistency=1

log_salve_updates=1(这个参数可能有问题)

在主库和从库查看gtid_mode状态:(show variables like 'gtid_mode';)

清除之前的slave信息:  在从库stop slave; reset slave; 在主库reset master;

在主库show master status\G;发现有Executer_Gtid_Set有了数据.这就是当前的Gtid.

binlog里查看GTID:  mysqlbinlog mysql-bin.000008 -vv >/tmp/gtid.sql.

 8.GTID在线搭建

 

 1.数据导出导入.

mysqldump -uroot -p -S /tmp/mysql3307.sock --master-data=2 --single-transaction  -A > /tmp/all.sql

---导出会有警告,因为会导出GTID.

查看导出文件,确定具体GTID---一般在第24行左右.(在前35)

从库导入:  mysql> source /tmp/all.sql;

 导入完成后查看gtid:  mysql> select @@global.gtid_purged;

发现@@global.gtid_purged是空的,查看导入数据过程发现错误.

提示:@@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty. 从库的@@GLOBAL.GTID_EXECUTED必须是空的才行.

查看@@GLOBAL.GTID_EXECUTED :    mysql> select @@global.gtid_executed;

设置GLOBAL.GTID_EXECUTED为空的方法执行mysql> reset master;

注意重新导入前必须确定@@global.gtid_executed为空. 重新数据导入即可.查看gtid.

 mysql> select @@global.gtid_purged;  ---与导出文件中的GTID必定一致.

 2.开启主从

change master to master_host='192.168.88.2',master_port=3307,master_user='rep',master_password='rep',master_auto_position=1;

----不用再定位pos点或GTID.最后参数master_auto_position不是表示定位pos作用,其意思是让数据库打开自动定位pos点功能.

然后从库开启: start slave;  show slave status;即可完成主从搭建.

3.步骤总结:

确定主从库都已打开gtid_mode=on;

1. 导出:mysqldump -uroot -p -S /tmp/mysql3307.sock --master-data=2 --single-transaction  -A > /tmp/all.sql

2.从库导入前 reset master;   select @@global.gtid_executed; (为空进行下一步)

3.从库导入并查看是否成功: source /tmp/all.sql 并查看select @@global.gtid_purged;

4.开启主从:change master to master_host='192.168.88.3',master_port=3307,master_user='rep',master_password='rep',master_auto_position=1;

5.从库 : start slave;  show slave status\G;

 4.Xtrabackup通过GTID在线搭建主从

1Xtrabackup_binlog_info文件中,包含global.gtid_purged='XXXXXX:XXXX'的信息。

2、然后到slave去手工的 SET GLOBAL.GTID_PURGED='XXXXXX:XXXX'

3、恢复备份,开启change master to 命令。

注意:如果系统运行了很久,无法找到GTID的编号,可以通过上面的方式进行查找。

 9.GTID跳过事务冲突

 1、这个功能主要跳过事务,代替原来的set global sql_slave_skip_counter = 1

2、由于在这个GTID必须是连续的,正常情况同一个服务器产生的GTID是不会存在空缺的。所以不能简单的skip掉一个事务,只能通过注入空事物的方法替换掉一个实际操作事务。

Retrieved_Gtid_Set: 02c8aa5e-a0cd-11e8-92c7-000c290206e2:4-6

Executed_Gtid_Set: 02c8aa5e-a0cd-11e8-92c7-000c290206e2:1-5, 053bd58c-a171-11e8-902d-000c290206e2:1

方法:show slave status \G :找到卡的事务GTID:

stop slave;

set gtid_next="6c9da32f-0513-11e4-a949-00e04c8a7573:1";  --跳过此事务.

begin;commit;

set gtid_next="AUTOMATIC";

start slave;

 10.MySQL GTID5.7新特性—在线启停

 老版本的MySQL GTID在开启的时候需要停服务,对服务器影响较大.

1.在每台服务器上设置所有事务都可以违反GTID的事务一致性

set global enforce_gtid_consistency=WARN;

这一步很重要,要确定在做下一步之前,错误日志中不能有警告.

2.在每一台数据库设置确保所有事务不影响GTID的事务一致性

set global enforce_gtid_consistency=ON;

3.在每一台数据库设置新事务是匿名的,同时允许GTID复制是匿名的或者是GTID

set global gtid_mode='OFF_PERMISSIVE';

4.在每一台数据库设置新事务是GTID的,同时允许GTID复制是匿名的或者是GTID

set global gtid_mode=ON_PERMISSIVE;

show status like 'ongoing_anonymous_transaction_count';

显示0值或者空值即可,如果非需要等待同步事务全部执行完成。

5.在每一台数据库设置:

set global gtid_mode='ON';

 11.GTID的限制:

1. 不支持非事务引擎(从库报错,stopslave; start slave; 忽略)

2. 不支持create table  select 语句复制(主库直接报错)

3. 不允许在一个SQL同时更新一个事务引擎和非事务引擎的表

4. 在一个复制组中,必须要求统一开启CTID或是关闭GTID

5. 开启DTID需要重启(5.7中不需要)

6. 开启DTID后,就不再使用原来的传统的复制方式

7. 对于create temporary table drop temporary table语句不支持

8. 不支持sql_slave_skip_counter

 12.MySQL5.7多源主从复制

 1.什么是多源主从?

多个主库一个从库.

 MySQL5.7.2上面添加了多源复制(Multi-Source)功能,意味着一个从库可以连多个主库,从而同时进行同步,但是如果是同一个表的话,会存在主键和唯一索引冲突的风险,需要提前做好规划.

 2.MySQL多源复制的原理

个人认为MySQL能实现多源复制的关键有两点:

1. MySQL5.7中的从库进行同步的SQL_THREADIO_THREAD可以并发执行,这使得使多数据源的binlog同时同步变为可能。

2. MySQL5.7中添加了channel(通道)来判别不同的数据源,这样slave可以非常简单的进行多数据源的配置与区分。

大概的多源复制过程

筛选复制数据源

配置栗子

复制实验

结论

每个通道都是一个slave去拉去masters的连接,每个通道对应一个IO_THEAD,我们运行不同的“change master” 命令对于每一个主服务器。我们需要用到 “for channel”这个参数来提供通信链接的名字。

 3.多源复制过程

slave 192.168.60.22:3306

master1 192.168.60.223307

master2 192.168.60.223308

主库授权: grant all on *.* to rep@'%' identified by '123456';

从库配置多通道复制

#只需在原有的复制命令加 for channel channel name

change master to master_host='192.168.60.22',master_port=3307,master_user='rep',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=154 for channel 'master1';

 

change master to master_host='192.168.60.22',master_port=3308,master_user='rep',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=154 for channel 'master2';

 

GTID下进行配置多源复制:

change master to master_host='192.168.60.22', MASTER_USER='rep', MASTER_PORT=3307,

MASTER_PASSWORD='123456',MASTER_AUTO_POSITION = 1 FOR CHANNEL 'master1';

 

相关通道命令

show slave status

show slave status for channel 'master1';

reset slave;

reset slave for channel 'master1';

stop slave for channel 'master1';

start slave for channel 'master1';

 

多源复制实验 

master1

create database test1;

master2

create database test2;

此时查看slave,发现test1test2已经同步到slave

复制冲突实验:

master1

create database test3;

master2

create database test3;

会报错!!!复制直接出错,所以,多源复制还是要进行差异化插入,如果相同数据进行操作,slave会直接出现复制异常,错误代码1007

异常解决:

stop slave;

set global sql_slave_skip_counter=1;

使用上述参数后,只能单独开启通道,只执行start slave会报错

start slave for channel 'master2';

start slave for channel 'master1';

MySQL5.7的多源复制,是在MySQL可以多线程同步后,依靠多线程所采取的复制模式,但是无法在master端对binlog进行筛选,所以相同操作的binlog进入slave后,slave因为无法应用而报错,MySQL分表分库后,此模式的使用可以非常简单的mergedata shards.或者备份多个节点数据库的数据到单独的机器。

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有