mysql多源复制详解

大家应该知道,mysql比起其他数据库,最大的特色是就是主从复制,不过5.7之前的版本最多就只支持一主多从的复制方式,对于一些统计类的需求,就需要跨库,这是比较麻烦的事情,以往只能交由数据库中间件(mycat等)去做这种事情,还有备份操作,也只能一个个库的用脚本去轮询或并发备份,不可谓不费时费力。然后,多源复制的概念出来了。

多源复制的概念最早是mariadb社区提出的,后来mysql官方积极引入到5.7的版本中来(5.6最新版也是没有这个功能的),percona就不说了,也是随后推出。这个功能很好的解决了上面说的问题,最直接的当然是省事省钱了,如果把并发复制也开启,在内网环境下,延时几乎是可以忽略的。

个人建议,多源复制不宜做唯一的从库,而是做第二/三从库或层级从库比较好,主要目的应该是统计库或备份库。因为通常来说,多源复制为了避免某些数据冲突是会忽略某些数据库和表的复制的,而为了提高数据库高可用,是需要整库同步的,例如MHA和PXC环境几乎就是要主从是一致的,这样就有冲突而导致不能做高可用了,所以,做第二/三从库或层级从库才可以避免。

前置环境说明

现在测试的架构是主库1的work1和主库2的work2,进行多源复制到从库3中,而且忽略系统库mysql库,这么简单我就不打算画图了,估计网上也有很多,因为后面内容不少,我也不想占版面了,所以随便说一下就算了。

主库1:mysql版本:阿里云rdsmysql5.6.34,ip地址:10.2.0.5

主库2:mysql版本:自建percona-server5.7.18,ip地址:10.2.0.6

从库3:mysql版本:自建percona-server5.7.18,ip地址:10.2.0.7

目的就是:

主库1---work1\

从库3

主库2---work2/

怎么搭建mysql数据库我就不说了,这点各位自行研究,我想要看这篇文章的人估计在搭建方面至少是没压力的,同时也假设是有一定业务的数据库存在,其实没有也可以,模拟就行。

然后,看下面的操作。

导出与导入数据库

就算不是做多源复制,普通的主从复制环境都需要把数据导出和导入数据,毕竟binlog不是一直都有记录的(保留策略问题),数据量多起来的话,让他从新跑也是不现实的。

而由于我们多源复制的原意是只复制有需求的数据库,如果使用xtrabackup就不太合适了,因为默认也是会备份mysql库的,这个时候用mysqldump就合适一些了,除非前面一个库用xtrabackup,下一个用mysqldump就可以。我觉得mysqlpump和mydumper也是可以尝试一下。

下面来看看操作

#从主库导出数据库
mysqldump -uroot -p‘******‘ -h10.2.0.5 -P3306 --triggers -R --single-transaction --no-autocommit --master-data=2 -q -e work1 >work1.sql
mysqldump -uroot -p‘******‘ -h10.2.0.6 -P3306 --triggers -R --single-transaction --no-autocommit --master-data=2 -q -e work2 >work2.sql

可能导出的时候会有个warnings的警告,说会导出设定GTID的sql,不过这个正是我们后面需要的东西,所以可以忽略。

然后,就导入到目的从库环境吧,只要数据不冲突,都可以导进去。理论上,多源复制要禁止一切同名数据库的存在,不然就不是多源复制了。不过,有一种情况我觉得可以尝试下,我个人还没试过,就是同一个库名,多源复制不同的数据表,各位有兴趣可以自行尝试,这里不展开。

#导入数据库到从库
mysql -uroot -p‘******‘ -h10.2.0.7 -P3306
>create database work1
>use work1 
>source work1.sql
>create database work2
>use work2 
>source work2.sql
#也可以这样
mysql -uroot -p‘******‘ -h10.2.0.7 -P3306 -e "create database work1;use work1;source work1.sql;"
mysql -uroot -p‘******‘ -h10.2.0.7 -P3306 -e "create database work2;use work2;source work2.sql;"

导完之后,如果严谨一些,就看看数据表是不是全都导进去了,其他就等下一步开始配置了。

配置多源复制环境

以下操作,大部分都是在从库执行的,主库最多就是授权一下,如果已经做过了主从架构,一般这个也是早就授权过的了,直接拿来用就可以的了。

如果配过主从复制环境,应该知道旧模式是要确定pos位置,新模式则是要设置GTID的编号。至于怎么确定,直接more看一下就知道了。

#看以下sql的备份文件
more work1.sql
    .
    .
    .
-- GTID state at the beginning of the backup 
--
SET @@GLOBAL.GTID_PURGED=‘3edae34c-6299-11e6-95cd-8038bc0c67be:1-6758,
4cdc2a74-6299-11e6-95ce-008cfaf595bc:1-38813008‘;
--
-- Position to start replication or point-in-time recovery from
--
-- CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.001284‘, MASTER_LOG_POS=3954096;
    .
    .
    .

这里不打算详细解析,有兴趣的可以看我另一篇关于搭建普通主从架构的文章,里面有详细解析。现在这里可以看到gtid和pos值,后面我们拿来用就可以了。

然后,进入正题:

首先,我们要把从库配置文件改一下,添加些东西。

#在从库的my.cnf配置文件中添加配置项,需要重启mysql实例
vim my.cnf
[mysqld]
master_info_repository=TABLE
relay_log_info_repository=TABLE
replicate_wild_do_table=work1.%
replicate_wild_do_table=work2.%
read-only
slave_parallel_workers = 4
#前面两个可以在线实现设置,目的就是把主从配置信息改为记录到表
SET GLOBAL master_info_repository = ‘TABLE‘;
SET GLOBAL relay_log_info_repository = ‘TABLE‘;

需要特别注意replicate_wild_do_table这个参数,这个参数的意思是只执行某个库或某个表的同步语句,其他库和表都不处理,从而达到选择性复制业务库的目的,这就不会有无用的数据了,也不会互相干扰。官方文档解析只能一个参数标记一个库,而且这个参数是全局通用,也就是说多源复制下,所有源频道都通用这个配置。开启只读read-only就不用多说了,多源复制一般就只有读的需求,就不要让他们有写库的可能了。并发复制slave_parallel_workers是5.6,5.7新出的功能,能有效加快复制的效率,特别5.7是支持事务并发复制的,速度相当可观,这里设置了每个复制连接有4个并发线程。

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

然后,在主库授权复制的账号,已做过同类账户授权的可以忽略

#在主库授权,已做过的可以忽略
mysql -uroot -p‘******‘ -h10.2.0.5 -P3306
grant replication slave on *.* to ‘rep‘@‘%‘ identified by ‘123123‘;
mysql -uroot -p‘******‘ -h10.2.0.6 -P3306
grant replication slave on *.* to ‘rep‘@‘%‘ identified by ‘123123‘;

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

好了,开始正式配置多源复制,这个GTID模式其实比起传统pos的模式更复杂一些,不过,未来都是用GTID多的了,所以我就拿GTID模式来做演示为主。

#登录进从库数据库
mysql -uroot -p‘******‘ -h10.2.0.7 -P3306
#先清空所有主从结构的记录
reset slave all;
#配置阿里云的数据库,这是GTID模式
change master to
master_host=‘10.2.0.5‘,
master_user=‘rep‘,
master_password=‘123123‘,
master_port=3306,
MASTER_AUTO_POSITION = 1
FOR CHANNEL ‘al_RDS‘;
#配置自建的数据库,这是GTID模式
change master to
master_host=‘10.2.0.6‘,
master_user=‘rep‘,
master_password=‘123123‘,
master_port=3306,
MASTER_AUTO_POSITION = 1
FOR CHANNEL ‘me_mysql‘;
#重置GTID值
reset master;
#设置GTID值
SET @@GLOBAL.GTID_PURGED=‘09cb91bf-2669-11e7-8b70-00163e0835ff:1-486646,3edae34c-6299-11e6-95cd-8038bc0c67be:1-6758,
4cdc2a74-6299-11e6-95ce-008cfaf595bc:1-38813008‘;

需要特别注意的两点是,多源复制提供了channel的标识,区分了不同的源频道,所以配置的时候就需要加上指定频道名称FOR CHANNEL ‘al_RDS‘;这样。而GTID的值和replicate_wild_do_table参数一样,默认是全局的配置,让源频道各取所需,所以,我们的gtid值,应该是所有*.sql文件的gtid值的合集,用‘,’号分隔,最终就出现我这个要设置这么多GTID的情况。

然后都配置完成了,就可以启动了,启动和关闭都可以指定特定的源频道,相当方便,下面列举一下命令。

#启动/关闭所有源频道
start/stop slave;
#启动/关闭单一的源频道
start/stop slave for channel ‘al_RDS‘;
#当然重置也是可以单独频道的
#RESET SLAVE FOR CHANNEL ‘al_RDS‘;
#查看状态也是可以单独的,不指定就是全部了
#show slave status for channel ‘al_RDS‘;

然后,看看状态,show slave status看看。

#在从库上执行命令
mysql -uroot -p‘******‘ -h10.2.0.7 -P3306
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.2.0.5
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.001297
          Read_Master_Log_Pos: 5607291
               Relay_Log_File: beifen1-relay-bin-al_rds.000030
                Relay_Log_Pos: 5607464
        Relay_Master_Log_File: mysql-bin.001297
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: work1.%,work2.%
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 5607291
              Relay_Log_Space: 5607767
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 2721321239
                  Master_UUID: 4cdc2a74-6299-11e6-95ce-008cfaf595bc
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 4cdc2a74-6299-11e6-95ce-008cfaf595bc:38888940-39258544
            Executed_Gtid_Set: 09cb91bf-2669-11e7-8b70-00163e0835ff:1-640645,
1db4cb1b-5e00-11e7-89eb-00163e046b4a:1-8,
3edae34c-6299-11e6-95cd-8038bc0c67be:1-6758,
4cdc2a74-6299-11e6-95ce-008cfaf595bc:1-39258544
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: al_rds
           Master_TLS_Version: 
*************************** 2. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.2.0.6
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000013
          Read_Master_Log_Pos: 246854093
               Relay_Log_File: beifen1-relay-bin-me_mysql.000004
                Relay_Log_Pos: 155502415
        Relay_Master_Log_File: mysql-bin.000013
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: work1.%,work2.%
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 246854093
              Relay_Log_Space: 155502632
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 253241
                  Master_UUID: 817498dc-2676-11e7-a673-00163e024674
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 09cb91bf-2669-11e7-8b70-00163e0835ff:514003-640645
            Executed_Gtid_Set: 09cb91bf-2669-11e7-8b70-00163e0835ff:1-640645,
1db4cb1b-5e00-11e7-89eb-00163e046b4a:1-8,
3edae34c-6299-11e6-95cd-8038bc0c67be:1-6758,
4cdc2a74-6299-11e6-95ce-008cfaf595bc:1-39258544
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: me_mysql
           Master_TLS_Version: 
2 rows in set (0.00 sec)

很长,我们看到有两条记录,其中Replicate_Wild_Do_Table,Executed_Gtid_Set是全局通用,两边都有,印证了我说的参数是全局的。然后各自的Retrieved_Gtid_Set是不同的,他们都自行选择了,相当智能。再看到Channel_Name就是他们不同的频道名字了。其他双yes和binlog,relaylog就不细说了,做过都知道看什么,现在是同步的。

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

如果是传统的模式,反而更简单,不用设置GTID的值,类似下面这样指定log文件名和pos即可,不用设置SET @@GLOBAL.GTID_PURGED就可以启动。

#设置频道一
change master to
master_host=‘10.2.0.5‘,
master_user=‘rep‘,
master_password=‘123123‘,
master_port=3306,
MASTER_LOG_FILE=‘mysql-bin.001284‘,
MASTER_LOG_POS=3954096
FOR CHANNEL ‘al_RDS‘;
#设置频道二
change master to
master_host=‘10.2.0.6‘,
master_user=‘rep‘,
master_password=‘123123‘,
master_port=3306,
MASTER_LOG_FILE=‘mysql-bin.000014‘,
MASTER_LOG_POS=67456
FOR CHANNEL ‘me_mysql‘;
#启动
start slave;

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

时间: 2024-10-01 17:02:48

mysql多源复制详解的相关文章

深入Java基础(四)--哈希表(1)HashMap应用及源码详解

继续深入Java基础系列.今天是研究下哈希表,毕竟我们很多应用层的查找存储框架都是哈希作为它的根数据结构进行封装的嘛. 本系列: (1)深入Java基础(一)--基本数据类型及其包装类 (2)深入Java基础(二)--字符串家族 (3)深入Java基础(三)–集合(1)集合父类以及父接口源码及理解 (4)深入Java基础(三)–集合(2)ArrayList和其继承树源码解析以及其注意事项 文章结构:(1)哈希概述及HashMap应用:(2)HashMap源码分析:(3)再次总结关键点 一.哈希概

MySQL UUID函数的详解(转)

MySQL UUID函数的详解 MySQL中可以有二类用于生成唯一值性质的工具:UUID()函数和自增序列,那么二者有何区别呢?我们就此对比下各自的特性及异同点: l  都可以实现生成唯一值的功能: l  UUID是可以生成时间.空间上都独一无二的值:自增序列只能生成基于表内的唯 一值,且需要搭配使其为唯一的主键或唯一索引: l  实现方式不一样,UUID是随机+规则组合而成的,而自增序列是控制一个值逐步增长的: l  UUID产生的是字符串类型值,固定长度为:36个字符,而自增序列产生的是整数

butterknife源码详解

butterknife源码详解 作为Android开发者,大家肯定都知道大名鼎鼎的butterknife.它大大的提高了开发效率,虽然在很早之前就开始使用它了,但是只知道是通过注解的方式实现的,却一直没有仔细的学习下大牛的代码.最近在学习运行时注解,决定今天来系统的分析下butterknife的实现原理. 如果你之前不了解Annotation,那强烈建议你先看注解使用. 废多看图: 从图中可以很直观的看出它的module结构,以及使用示例代码. 它的目录和我们在注解使用这篇文章中介绍的一样,大体

MySQL之SQL优化详解(三)

目录 MySQL 之SQL优化详解(三) 1. 索引优化 2. 剖析报告:Show Profile MySQL 之SQL优化详解(三) 1. 索引优化 一旦建立索引,select 查询语句的where条件要尽量符合最佳左前缀的原则,如若能做到全值匹配最好. 索引优化的第一个前提就是建好索引,第二个就是避免索引失效 索引失效的场景 如果索引了多列,要遵守最左前缀法则.指的是查询从索引的最左前列开始并且不跳过索引中的列 不在索引列上做任何操作(计算.函数.(自动or手动)类型转换),会导致索引失效而

Android编程之Fragment动画加载方法源码详解

上次谈到了Fragment动画加载的异常问题,今天再聊聊它的动画加载loadAnimation的实现源代码: Animation loadAnimation(Fragment fragment, int transit, boolean enter, int transitionStyle) { 接下来具体看一下里面的源码部分,我将一部分一部分的讲解,首先是: Animation animObj = fragment.onCreateAnimation(transit, enter, fragm

mysql改删数据详解

修改表数据 先给class表增加几行数据以便操作 mysql> insert into class mysql> (sname,gender,company,fanbu) mysql> values mysql> ('xiaoxiao','男','腾讯',200), mysql> ('xiaoqing','女','百度',300); mysql> select * from class; 修改数据 将xiaoxiao的fanbu数据增加200 mysql> upd

mysql explain执行计划详解

1).id列SELECT识别符.这是SELECT查询序列号.这个不重要,查询序号即为sql语句执行的顺序 2).select_type列常见的有: A:simple:表示不需要union操作或者不包含子查询的简单select查询.有连接查询时,外层的查询为simple,且只有一个 B:primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary.且只有一个 C:union:union连接的两个select查询,第一个查询是de

MySQL 执行计划explain详解

MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的. 调用EXPLAIN 在select之前添加explain,mysql会在查询上设置一个标记,当执行查询计划时,这个标记会使其返回关于执行计划中每一步的信息,而不是执行它.它会返回一行或多行信息,显示出执行计划中的每一部

PHP mysql与mysqli事务详解

官方对PHP连接到MySQL数据库服务器的三种主要的API简介如下: http://php.net/manual/zh/mysqli.overview.php PHP mysql与mysqli事务详解 在PHP中,mysqli 已经很好的封装了mysql事务的相关操作.如下示例: $sql1 = "update User set ScoreCount = ScoreCount +10 where ID= '123456'"; $sql2 = "update ScoreDeta