码迷,mamicode.com
首页 > 数据库 > 详细

企业——MYSQL(基于GTID)的主从复制

时间:2018-10-25 15:45:26      阅读:320      评论:0      收藏:0      [点我收藏+]

标签:缓解   eve   uid   trap   into   ase   start   io线程   width   

一、什么是主从复制?
   主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是准实时的业务数据库。


二、主从复制的作用(好处,或者说为什么要做主从)
   1、做数据的热备,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
   2、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
   3、读写分离,使数据库能支撑更大的并发。在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度。


三、主从复制的原理:
   1.数据库有个bin-log二进制文件,记录了所有sql语句。
   2.我们的目标就是把主数据库的bin-log文件的sql语句复制过来。
   3.让其在从数据的relay-log重做日志文件中再执行一次这些sql语句即可。
   4.下面的主从配置就是围绕这个原理配置
   5.具体需要三个线程来操作:
    --(1).binlog输出线程:每当有从库连接到主库的时候,主库都会创建一个线程然后发送binlog内容到从库。在从库里,当复制开始的时候,从库就会创建两个线程进行处理:

    --(2).从库I/O线程:当START SLAVE语句在从库开始执行之后,从库创建一个I/O线程,该线程连接到主库并请求主库发送binlog里面的更新记录到从库上。从库I/O线程读取主库的binlog输出线程发送的更新并拷贝这些更新到本地文件,其中包括relay log文件。

    --(3).从库的SQL线程:从库创建一个SQL线程,这个线程读取从库I/O线程写到relay log的更新事件并执行。

   可以知道,对于每一个主从复制的连接,都有三个线程。拥有多个从库的主库为每一个连接到主库的从库创建一个binlog输出线程,每一个从库都有它自己的I/O线程和SQL线程。

大体步骤:
步骤一:主库db的更新事件(update、insert、delete)被写到binlog
步骤二:从库发起连接,连接到主库
步骤三:此时主库创建一个binlog dump thread线程,把binlog的内容发送到从库
步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log.
步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db.

请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,
以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。


四.试验过程

1.实验环境
   redhat6.5
   iptables和selinux关闭
   master:vm1 (172.25.254.1)
   slave:vm2,3 (172.25.254.2 172.25.254.3)


2.数据同步

 在vm1,2,3上:
    安装mysql,安全初始化
   yum install mysql-server -y
   tar xf mysql-5.7.17-1.el6.x86_64.rpm-bundle.tar
   ls
   yum reinstall mysql-community-client-5.7.17-1.el6.x86_64.rpm mysql-community-common-5.7.17-1.el6.x86_64.rpm mysql-community-libs-5.7.17-1.el6.x86_64.rpm  mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm mysql-community-server-5.7.17-1.el6.x86_64.rpm -y
   /etc/init.d/mysqld start
       技术分享图片

 在vm1(master)上:master是多线程的
   vim /etc/my.cnf
    在[mysqld]下添加一下参数
    log-bin=mysql-bin   ##启动二进制日志系统   二进制文件名
    binlog-do-db=test   ##二进制需要同步的数据库名,如果需要同步多个库,例如要再同步 westos
库,再添加一行“binlog-do-db=westos”,以此类推
    server-id=1   ##必须为 1 到 232–1 之间的一个正整数值
    binlog-ignore-db=mysql  ##禁止同步 mysql 数据库
   /etc/init.d/mysqld start

   mysql -p
    mysql> grant replication slave on *.* to repl@‘%‘ identified by ‘Wang+1212‘;  //用户授权
    mysql>Flush privileges;
      技术分享图片


 调试:
    在 master 上用下面的命令查看
    mysql> show master status;      ##记录 File 和 Position 的值,下面会用到。

 在vm2(slave)上:
    mysql> change master to master_host=‘172.25.254.1‘ , master_user=‘westos‘ , master_password=‘westos‘ , master_log_file=‘mysql-bin.000001‘, master_log_pos=154;
    Query OK, 0 rows affected, 2 warnings (0.18 sec)
      技术分享图片

    mysql> start slave;
    Query OK, 0 rows affected (0.07 sec)

    mysql> show slave status\G;
        。。。
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
        。。。
    ##如果都是 yes,表示从库的 I/O,Slave_SQL 线程都正确开启.表明数据库正在同步
      技术分享图片

 

 测试:

 在vm1(master)上:
    mysql> create database westos;
        Query OK, 1 row affected (0.35 sec)
    mysql> use westos;
    mysql>creata table usertb(
        ->username varchar(20) not null,
        ->password varchar(25) not null);
    mysql> insert into usertb values (‘wf‘,‘111‘);

       技术分享图片

 

 

 在vm2(slave)上:       查看可以同步到新建的数据库westos
    mysql> show databases;
    mysql> use westos;
    mysql> show tables;
    mysql> select * from usertb;

==============================================================================================
Slave_IO_Running:NO的原因:用户认证,防火墙或者网络的问题  IO是异步的(同步安全,但是太慢,因此使用半同步复制,需要一个半同步的插件,专开一个线程等待IO回应,然后继续同步)
 
Slave_SQL_Running:NO的原因:日至不同步(这个是NO,可能没那么严重,可能是因为回放文件的时候,和本来的数据有冲突,可以手动解决)

防止加重冲突越来越高(冲突来源:因为master是多线程的,SQL是单线程的)当master更加繁忙的时候,会加重SQL的延迟,数据不同步的情况,解决方法:并行复制

基于GTID的模式:
有GTID NEXT,通过这个才读取之后的数据,这个是不需要手动制定的
==============================================================================================

3.开启GTID模式(基于GTID的主从复制)

 在vm1,2上:
   vim /etc/my.cnf     ##数据库的配置文件  添加有关GTID的模块
    gtid_mode=ON     ##开启GTID的模块
    enforce-gtid-consistency=true    ##强制一直保持GTID
   /etc/init.d/mysqld restart     ##因为重写了事件,就会重新写一个二进制文件了

 在vm1上,只要更改了事件,就会自动创建一个新的二进制日志文件:

   二进制文件所在目录:
    cd /var/lib/mysql
    cat mysql-bin.index
        ./mysql-bin.000001
        ./mysql-bin.000002
        ./mysql-bin.000003
        ./mysql-bin.000004
  
 在vm2(slave)上重新添加master:
   mysql -p
   stop mysql;
   change master to master_host=‘172.25.254.1‘,master_user=‘repl‘,master_password=‘Wang+1212‘,MASTER_AUTO_POSITION=1;    ## MASTER_AUTO_POSITION=1 动态获取master的数据
   start slave;
   show slave status\G;
        。。。
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
        。。。

 测试:

 在vm1上:
    mysql> insert into usertb values (‘wf1‘,‘111‘);
        Query OK, 1 row affected (0.35 sec)
    mysql> select * from usertb;
 在vm2上:       查看可以同步到新建的信息
    mysql> use westos;
    mysql> select * from usertb;

 查看进程信息:
    mysql> show processlist;
        ##上面的是IO线程  下面的是SQL线程

4.并行复制(解决复制延迟的问题)
=======================================================================================
 判断主从延迟
   mysql> show slave status\G;
    Seconds_Behind_Master:0   ##落后master多少秒
=======================================================================================

 配置主从复制:
   将原本的默认的基于库的并行复制的方式,更改为基于组提交的并行复制方式。

 在vm2(slave)上:

   在数据库中:
   mysql> use mysql;
   mysql> select * from slave_master_info;
    Empty set (0.00 sec)    ##在默认基于库的并行复制模式下,这个是空的

   vim /etc/my.cnf
    slave-parallel-type=LOGICAL_CLOCK
        ##默认是DATABASE,基于库的并行复制;LOGICAL_CLOCK:基于组提交的并行复制
    slave-parallel-workers=16
        ##原来的SQL变成了调度进程 slave-parallel-workers=16(不要设置为1,经过中转,会更慢)
    master_info_repository=TABLE
    relay_log_info_repository=TABLE
    relay_log_recovery=ON
  /etc/init.d/mysqld restart


5.IO异步,更改为半同步复制

 在vm1(master)上:
   mysql -p
   show processlist;    ##查看进程列表
   mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master.so‘;   ##安装插件
   mysql> show plugins;
   mysql> SET GLOBAL rpl_semi_sync_master_enabled=1
   mysql> show status like ‘%rpl%‘;   ##查看主从复制的状态

 在vm2(slave)上:
   mysql -p
   show processlist;    ##查看进程列表
   mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘semisync_slave.so‘;   ##加入插件
   mysql> show plugins;    ##查看插件
   mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1
   mysql> show status like ‘%rpl%‘;   ##查看主从复制的状态    现在是关闭的
   mysql> stop slave io_thread;       ##如果不执行这两步的话,主从复制的状态是OFF
   mysql> start slave io_thread;
   mysql> show status like ‘%rpl%‘;   ##查看主从复制的状态    现在是开启的


 测试:
 (1)
 在vm1上:
   mysql> insert into usertb values (‘wf2‘,‘222‘);
   mysql> select * from usertb;
   mysql> show status like ‘%rpl%‘;   
        ##这时就可以看到 Rpl_semi_sync_master_yes_tx 1  通过主从复制成功复制了一次

 在vm2上:
   mysql> select * from usertb;   ##可以查看到刚才添加的信息

 (2)
 在vm2上:
   mysql> stop slave io_thread;

 在vm1上:
   mysql> insert into usertb values (‘wf3‘,‘333‘);
   mysql> select * from usertb;
   mysql> show status like ‘%rpl%‘;   
        ##这时就可以看到 Rpl_semi_sync_master_no_tx 1  通过主从复制失败复制了一次

 注意:MYSQL默认的是异步复制,可以修改复制方式为半同步复制,也可以根据需求修改半同步复制的一些参数,比如:时间。但是需要注意的是,如果在设定的时间内master到得不到slave的回复,那么复制的方式就会变回异步复制的方式,因此,,如果设置为半同步复制的话,参数的等待的时间需要设定到无穷大 


6.如果写操作较少,而读操作很多时,可以采取这种结构。你可以将读操作分布到其它的 slave,从而减小
master 的压力。但是,当 slave 增加到一定数量时,slave 对 master 的负载以及网络带宽都会成为一个严重
的问题。这种结构虽然简单,但是,它却非常灵活,足够满足大多数应用需求。当设置 log_slave_updates 时,你可以让 slave 扮演其它 slave 的 master。此时,slave 把 SQL 线程执行的事
件写进行自己的二进制日志(binary log),然后,其它的 slave 可以获取这些事件并执行它,从而有效缓解
master 的压力  (vm1 -> vm2 -> vm3) 缓解master的压力,不会因为master坏了,而使服务用不了
   (一主多从,用于读多写少的场景)

 在vm2上:
   vim /etc/my.cnf
    ....
    server-id=2
    log-bin=mysql-bin
    binlog-ignore-db=mysqlbinlog-do-db=test
    log-slave-updates
    ....
   /etc/init.d/mysqld restart

 在vm2上创建同步帐户,并给予权限:
   mysql> GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* TO westos@‘172.25.254.2‘
    IDENTIFIED BY ‘westos‘;
   mysql>Flush privileges;
   mysql> show master status;

 在vm3上添加配置:
   vim /etc/my.cnf
    server-id=3
   /etc/init.d/mysqld start

 在vm3上执行一下命令:
   mysql> change master to master_host=‘‘, master_user=‘westos‘,
    master_password=‘westos‘, master_log_file=‘mysql-bin.000001‘,master_log_pos=217;
   mysql> slave start;
   mysql> show slave status\G;
    .....
    Slave_IO_Running: Yes    ##数据发送过来,保存到reloy.log 如果数据没有发送过来,如果是NO的话
    Slave_SQL_Running: Yes   ##用于作回放reloy.log 单线程 延迟更高 解决:并行复制
    .....


7.全同步(无中心化)
通过一致性协议 -> 推送到每一个节点 -> 判断是否可执行 -> 可执行全部节点执行,不可执行的话,全部节点不执行

 全同步的实验步骤:
   注意:将前面的所有服务全部停掉,并且删除服务

   /etc/init.d/mysqld stop
   chkconfig mysqld off
   cd /var/lib/mysql
   ls
   rm -fr *
  

    日至存储格式  奇数节点(最多9个,最少3个)
   vim /etc/my.cnf
    server_id=1
    gtid_mode=ON
    enforce_gtid_consistency=ON
    master_info_repository=TABLE
    relay_log_info_repository=TABLE
    binlog_checksum=NONE
    log_slave_updates=ON
    log_bin=binlog
    binlog_format=ROW

    transaction_write_set_extraction=XXHASH64
    loose-  group_replication_group_name="b8b8d7dd-9312-4539-971c-b013f49d6e51"    ##组名 UUID 可以随意写
    loose-group_replication_start_on_boot=off
    loose-group_replication_local_address= "172.25.0.1:24901"
    loose-group_replication_group_seeds= "172.25.0.1:24901,172.25.0.2:24901,172.25.0.3:24901"
        ##启动数据库示例 组所有节点
    loose-group_replication_bootstrap_group=off
    loose-group_replication_ip_whitelist="172.25.0.0/24"
    loose-group_replication_enforce_update_everywhere_checks=on
    loose-group_replication_single_primary_mode=off 默认单组模式  将其设置为off
    ##默认不生效,数据库没有插件,加参数loose,不会影响数据库的启动
   /etc/init.d/mysqld restart

   mysql -p
    SET SQL_LOG_BIN=0; 关闭二进制日志
    GRANT REPLICATION SLAVE ON *.* TO repl_user@‘%‘ IDENTIFIED BY ‘Wang+1212‘;  创建用户
    reset master   ##清空原数据
    SET SQL_LOG_BIN=1; 开启二进制日志

    CHANGE MASTER TO MASTER_USER=‘repl_user‘,MASTER_PASSWORD=‘Wang+1212‘ FOR CHANNEL ‘group_replication_recovery‘;   ##添加到组中

    INSTALL PLUGIN group_replication SONAME ‘group_replication.so‘;

在第一个节点上做这个操作:初始化节点,设置组的主节点
    SET GLOBAL group_replication_bootstrap_group=ON;
    START GROUP_REPLICATION;
    SET GLOBAL group_replication_bootstrap_group=OFF;

在其余的节点执行:
    START GROUP_REPLICATION;
    mysql> select * from performance_schema.replication_group_members;

 在vm1上:
   mysql> select * from performance_schema.replication_group_members;
   mysql> create databases wf;
   mysql> use wf;
   mysql> create table t1 (c1 int primary key ,c2 text not null);
   mysql> insert into t1 values (1,‘111‘);

 测试:
 分别在不同的服务器上,添加信息
 

企业——MYSQL(基于GTID)的主从复制

标签:缓解   eve   uid   trap   into   ase   start   io线程   width   

原文地址:https://www.cnblogs.com/wf-aiyouwei/p/9849656.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!