zoukankan      html  css  js  c++  java
  • GTID主从 与 传统主从复制

    1.主从复制

    1.)普通主从复制:

      普通主从复制主要是基于二进制日志文件位置的复制,因此主必须启动二进制日志记录并建立唯一的服务器ID,复制组中的每个服务器都必须配置唯一的服务器ID。如果您省略server-id(或者明确地将其设置为其默认值0),则主设备将拒绝来自从设备的任何连接。

    2.) GTID 主从: 

    (1.)基本概念

      MySQL 5.6 的新特性之一,全局事务标识符(GTID)是创建的唯一标识符,并与在源(主)服务器上提交的每个事务相关联。此标识符不但是唯一的,而且在给定复制设置中的所有服务器上都是唯一的。所有交易和所有GTID之间都有一对一的映射关系 。它由服务器ID以及事务ID组合而成。这个全局事务ID不仅仅在原始服务器上唯一,在所有存在主从关系 的mysql服务器上也是唯一的。正是因为这样一个特性使得mysql的主从复制变得更加简单,以及数据库一致性更可靠。一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。

      一个GTID被表示为一对坐标,用冒号(:)分隔,如下所示:GTID = source_id:transaction_id,source_id标识的源服务器。通常情况下,服务器 server_uuid用于这个目的。这transaction_id是一个序列号,由在此服务器上提交事务的顺序决定 .

    在传统的主从复制slave端,binlog是不用开启的,但是在GTID中slave端的binlog是必须开启的,目的是记录执行过的GTID(强制)。GTID用来代替classic的复制方法,不在使用binlog+pos开启复制。而是使用master_auto_postion=1的方式自动匹配GTID断点进行复制。

      mysql的主从复制是十分经典的一个应用,但是主从之间总会有数据一致性(data consistency )的问题,一般情况从库会落后主库几个小时,而且在传统一主多从(mysql5.6之前)的模型中当master down掉后,我们不只是需要将一个slave提成master就可以,还要将其他slave的同步目的地从以前的master改成现在master,而且bin-log的序号和偏移量也要去查看,这是十分不方便和耗时的,但mysql5.6引入gtid之后解决了这个问题。

    红色代表GTID,绿色代表传统主从:
    image

    (2.)GTID的工作原理:

    1、当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中。
    2、binlog传输到slave,并存储到slave的relaylog后,读取这个GTID的这个值设置gtid_next变量,即告诉Slave,下一个要执行的GTID值。
    3、sql线程从relay log中获取GTID,然后对比slave端的binlog是否有该GTID。
    4、如果有记录,说明该GTID的事务已经执行,slave会忽略。
    5、如果没有记录,slave就会执行该GTID事务,并记录该GTID到自身的binlog,
       在读取执行事务前会先检查其他session持有该GTID,确保不被重复执行。
    6、在解析过程中会判断是否有主键,如果有就用二级索引,如果没有就用全部扫描。
    

    2.GTID参数配置

    [mysqld]
    #GTID:
    server_id=1 #服务器id
    gtid_mode=on #开启gtid模式
    log_slave_updates ## 表示即可以当从也可以当主
    enforce_gtid_consistency=on #强制gtid一致性,开启后对于特定create table不被支持
    
    #binlog
    log_bin=master-binlog
    #log-bin=/data/mysql/mysql-bin.log    //binlog日志文件,(文件名如果是绝对路径,必须指定索引文件)
    #log_bin_index =    /var/lib/mysql/mysql-bin.index     //是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录
    log-slave-updates=1 
    binlog_format=row #binlog日志格式,强烈建议,其他格式可能造成数据不一致
    expire_logs_days=7            //binlog过期清理时间
    
    
    #relay logskip_slave_start=1
    

    2、从slave:

    与主的配置没有区别,仅仅只是server_id不一致。

    3.配置主从

    1.)master:

    创建并授权salve远程访问的用户:

    GRANT REPLICATION SLAVE ON *.* TO root@192.168.153.167 IDENTIFIED BY 'ly123';
    flush privileges;
    

    查看授权slave用户表:

    show grants for user@localhost;
    

    查看binlog信息:show master status;

    2.)GTID—slave;(注意:GTID主从必须启用MASTER_AUTO_POSITION而且不能跟bin与pos同时配置。)

    CHANGE MASTER TO MASTER_HOST='192.168.153.167',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='ly123', master_log_file='mysql-bin.000003',master_log_pos=308;
    start slave;
    show slave statusG
    

    关键:在配置文件中启用GTID的情况下,change语句才是决定启用GTID还是传统主从的关键。

    进行主备切换的时候,一般都会先对主库进行只读操作(on),然后主备同步完成后,再把备库置为可读写(off)。这样可以避免切换的过程中双写引起脏数据。:set global read_only=on/off

    4.特殊情况下,需要重置主从

    stop slave;

    reset slave all; #重置全部的从信息

    reset master; #重置主

    5.事物跳过(传统与GTID的跳过方法不同)

    1.传统

    set global sql_slave_skip_counter = 1;

    可以忽略N个事件(event),通常一个SQL是一个事件。

    2.GTID跳过事务冲突

    首先,我们需要先查看当前SLAVE复制的进度:SHOW SLAVE STATUSG

    Retrieved_Gtid_Set:aaa-bbb-ccc-ddd:N   (表示收到的事务)
    Executed_Gtid_Set:aaa-bbb-ccc-ddd:N    (表示已经执行完的事务)
    

    看Executed_Gtid_Set 到了31这个事务GTID位置,在这下一个位置(32)上发生错误。这时候,我们需要手工调整SLAVE已清除的GTID列表 GTID_PURGED,人为通知SLAVE哪些事务已经被清除了,后续可以忽略:

    STOP SLAVE;
     RESET MASTER;
     SET @@GLOBAL.GTID_PURGED = “3a16ef7a-75f5-11e4-8960-deadeb54b599:1-283,f2b6c829-9c87-11e4-84e8-deadeb54b599:1-32”;
     START SLAVE;
    

    上面这些命令的用意是,忽略 f2b6c829-9c87-11e4-84e8-deadeb54b599:32 这个GTID事务,下一次事务接着从 33 这个GTID开始,即可跳过上述错误。

    从服务器上负责同步的有二类线程: 1) IO thread 2) SQL thread

    Slave_IO_Running:从服务器正从主服务器上读取BINLOG日志,并写入从服务器的中继日志.
    Slave_SQL_Running:进程正在读取从服务器的BINLOG中继日志,并转化为SQL执行

    IO thread 决定了Retrieved_Gtid_Set
    SQL thread 决定了Executed_Gtid_Set

    IO thread负责获取master上的binary log, 然后多个sql threads负责执行。由于IO thread先于SQL thread,Retrieved_Gtid_Set可能会略多于Executed_Gtid_Set。比如: SHOW slave STATUS G

    .......
    .......
    Retrieved_Gtid_Set: 67cd9435-7cae-11e2-aa8d-00241db92e69:1-9
    Executed_Gtid_Set: 67cd9435-7cae-11e2-aa8d-00241db92e69:1-7 
    Auto_Position: 1
    

    1.)注入空事务:

    stop  slave;
    
    SET GTID_NEXT='aaa-bbb-ccc-ddd:N';    #要想跳过错误的GTID或则是想要跳过的GTID,就需要指定下一个事物的执行版本
    
    BEGIN; COMMIT;    #注入一个空事务
    
    SET GTID_NEXT='AUTOMATIC';  #自动寻找GTID事务
    
    一旦所有事务标识符以这种方式使用空事务恢复后,您必须刷新并清除从属服务器的二进制日志,如下所示,其中 N是当前二进制日志文件名称 的非零后缀;或者reset  slave;
    FLUSH LOGS;
    PURGE BINARY LOGS TO 'master-bin.00000N';
    
    start  slave;
    

    2.)重置master方法跳过错误

    mysql> STOP SLAVE;
    mysql> RESET MASTER;
    mysql> SET @@GLOBAL.GTID_PURGED ='8f9e146f-0a18-11e7-810a-0050568833c8:1-4'
    mysql> START SLAVE;

    注意:在GTID主从的建立初期,slave的数据一定要是从master mysqldump过去的并且更加--all-databases参数。否则手动补齐的数据会出现slave_sql_running为NO的情况,这是因为主的操作记录会保存在GTID与binlog中,然后slave会同步主的GTID与binlog并进行相应的操作,这时两边的数据虽然是一致的,但是同步过来master的GTID中包含了主做过的一些sql操作,而此时slave的环境不满足sql语句的执行就会冲突。解决办法是:1.)不断的执行跳过事务的操作直到没有报错。2.)刷新master的GTID“reset master”然后重新再slave执行change同步。

  • 相关阅读:
    [Erlang05]gen_server怎么去写eunit?
    [Erlang04]为什么有了rpc还有net_kernel:connect/1?
    [Erlang03]Erlang有哪些好用的静态分析工具?
    [SIP01]SIP Header Fields里面各字段用途
    [SIP00]SIP 概念总结
    [Erlang00]:gen_server:reply/2
    Makefile教程
    Linux 环境下开发 STM32
    Ubuntu 18.04 + ROS Melodic + TurtleBot3仿真
    Ubuntu系统鼠标不能点击
  • 原文地址:https://www.cnblogs.com/ly0629/p/10907946.html
Copyright © 2011-2022 走看看