美文网首页
MySQL-lesson09-主从复制高级功能

MySQL-lesson09-主从复制高级功能

作者: noodlesbook | 来源:发表于2020-02-06 15:53 被阅读0次

    1、延时从库

    1、逻辑损坏怎么办?
    延时从库:从库落后于主库一段时间,一般企业建议3-6小时;利用延时从库恢复
    原理:IO线程不延时,SQL线程延时执行;

    # 开启延时从库
    stop slave;
    change master to master_delay = 300;        //单位为秒
    start slave;
    show slave status\G
    SQL_Delay:300
    
    # 关闭延时从库
    stop slave;
    change master to master_delay = 0;        //单位为秒
    start slave;
    

    2、主库误操作,怎么使用延时从库恢复?

    1. 立即停止主库业务,立即停止从库SQL线程
      stop slave sql_thread;
    2. 手工模拟sql线程工作,并截至到误操作之前
      (1)读取relay-log.info,截取到上次执行到的位置,作为继续执行relay-log的起点 ;
      (2)分析relay-log内容,获取到误操作之前位置点。
      (3)截取这段日志,恢复到从库
    3. 从库切为主库,原主库切为从库

    故障模拟:
    (1)模拟数据

     pc [(none)]>create database delay charset utf8;
     pc [(none)]>use delay;
     pc [delay]>create table t1(id int);
     pc [delay]>insert into t1 values(1),(2),(3);
     pc [delay]>commit;
     pc [delay]>drop database delay;
    

    (2)停止从库sql线程
    pc [test]>stop slave sql_thread;

    (3)读取从库relay-log 信息

     pc [test]>show slave status\G
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 10.0.0.51
                      Master_User: repl
                      Master_Port: 3307
                    Connect_Retry: 10
                  Master_Log_File: mysql-bin.000004
              Read_Master_Log_Pos: 1422
                   Relay_Log_File: db01-relay-bin.000002
                    Relay_Log_Pos: 283
    

    起始位置为283;

    • 找到误删除位置
     pc [test]>show relaylog events in 'db01-relay-bin.000002';
    +-----------------------+-----+-------------+-----------+-------------+---------------------------------------+
    | Log_name              | Pos | Event_type  | Server_id | End_log_pos | Info                                  |
    +-----------------------+-----+-------------+-----------+-------------+---------------------------------------+
    ···
    | db01-relay-bin.000002 | 692 | Query       |         7 |        1422 | drop database delay                   |
    +-----------------------+-----+-------------+-----------+-------------+---------------------------------------+
    10 rows in set (0.00 sec)
    

    drop启始位置为692;

    (4)截取relay-log日志
    cd /data/3308/data/
    mysqlbinlog --start-position=283 --stop-position=692 db01-relay-bin.000002>/tmp/relay.log

    (5)恢复relay-log
    mysql -uroot -S /data/3308/mysql.sock //登录从库
    source /tmp/relay.log

    (6)此时从库的数据是完整的;从库切换为主库,原主库切换为从库

    3、过滤复制
    4、不能保证主库做的操作,从库一定能做。
    5、高可用?自动 failover

    2、半同步复制

    定义:尽可能保证主从数据一致性,会牺牲主库一定的性能;有设定超时时间,10秒钟,如果从库超过这个时间没有返回ACK,强制切换为异步复制过程。

    半同步复制存在的原因:
    当主库dump线程将binlog日志发送给从库IO线程,存储到TCP/IP缓存中,如果此时从库宕机或关机了,存在缓存中的数据有丢失的风险;

    • 半同步复制:当从库存在TCP/IP缓存中的数据写入到relay-log日志中,返回给主库一个ACK确认,主库才会commit操作;
      有一定数据安全性的保证,但主从数据不是完全一致性。
      5.6以后半同步复制改为group commit,性能提高,可以推荐使用半同步。

    • 同步复制:当从库SQL线程执行完relay-log日志,返回给主库一个ACK确认,主库commit,才会执行下一个操作;会牺牲主库的性能;
      也就是说当主库传给从库一个事务,只有当从库执行完这个事务与主库一致,主库才会执行下一个操作。

    配置半同步复制

    # 加载插件,如果要永久生效,加到配置文件中
    主:
    INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
    从:
    INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
    
    # 查看是否加载成功:
    show plugins;
    
    # 启动:
    主:
    SET GLOBAL rpl_semi_sync_master_enabled = 1;
    从:
    SET GLOBAL rpl_semi_sync_slave_enabled = 1;
    
    # 重启从库上的IO线程
    STOP SLAVE IO_THREAD;
    START SLAVE IO_THREAD;
    
    # 查看是否在运行
    主:
    show status like 'Rpl_semi_sync_master_status';
    从:
    show status like 'Rpl_semi_sync_slave_status';
    

    3、过滤复制

    定义:写操作在主库发生,将多个从库的业务拆分,即A数据复制1从库,B数据复制到2从库。

    show master status;
    Binlog_Do_DB           //白名单,binlog记录的库
    Binlog_Ignore_DB       //黑名单,binlog忽略的库
    
     pc [world]>show slave status\G
    *************************** 1. row ***************************
                  Replicate_Do_DB:                  //白名单,复制的库
              Replicate_Ignore_DB:                //黑名单,忽略的库
               Replicate_Do_Table:              //表的白名单,复制的表
           Replicate_Ignore_Table:           //表的黑名单,忽略的表
          Replicate_Wild_Do_Table:         //模糊的白名单,t**,以t开头的表复制
      Replicate_Wild_Ignore_Table:        //模糊的黑名单,忽略t开头的表复制
    

    2.1 过滤复制配置

    前提: 主从复制已开启,在从库配置

    [root@db01 ~]# vim /data/3309/my.cnf 
    [mysqld]
    replicate_do_db=ppt
    replicate-do-table=test.t1
    replicate-wild-do-table=test.t*
    
    # 重启从库
    [root@db01 ~]# systemctl restart mysqld3309
    or
    mysqladmin -S /data/3308/mysql.sock shutdown
    mysqld_safe --defaults-file=/data/3308/my.cnf &
    
    主库测试:
    Master [(none)]>create database word;
    Query OK, 1 row affected (0.00 sec)
    Master [(none)]>create database ppt;
    Query OK, 1 row affected (0.00 sec)
    Master [(none)]>create database excel;
    Query OK, 1 row affected (0.01 sec)
    

    4、 GTID复制

    3.1 环境准备

    image.png
    1. 停库
      [root@db01 ~]# /etc/init.d/mysqld stop
    2. 删除data目录
      [root@db01 ~]# rm -fr /application/mysql/data/*
    3. 备份3台机器的配置文件
      mv /etc/my.cnf /tmp
    4. 初始化配置文件
      master:10.0.0.51
    vim /etc/my.cnf
    [mysqld]
    basedir=/application/mysql
    datadir=/application/mysql/data
    socket=/tmp/mysql.sock   
    log_error=/var/log/mysql.log   
    log-bin=/data/mysql/mysql-bin
    binlog_format=row
    skip-name-resolve
    server_id=51   
    gtid-mode=on
    port=3306
    autocommit=0
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    [client]
    socket=/tmp/mysql.sock
    prompt=\\ pc [\\d]>
    

    slave:10.0.0.52

    vim /etc/my.cnf
    [mysqld]
    basedir=/application/mysql
    datadir=/application/mysql/data
    socket=/tmp/mysql.sock   
    log_error=/var/log/mysql.log   
    log-bin=/data/mysql/mysql-bin
    binlog_format=row
    skip-name-resolve
    server_id=52
    gtid-mode=on
    port=3306
    autocommit=0
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    [client]
    socket=/tmp/mysql.sock
    prompt=\\ pc [\\d]>
    

    slave:10.0.0.53

    vim /etc/my.cnf
    [mysqld]
    basedir=/application/mysql
    datadir=/application/mysql/data
    socket=/tmp/mysql.sock   
    log_error=/var/log/mysql.log   
    log-bin=/data/mysql/mysql-bin
    binlog_format=row
    skip-name-resolve
    server_id=53
    gtid-mode=on
    port=3306
    autocommit=0
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    [client]
    socket=/tmp/mysql.sock
    prompt=\\ pc [\\d]>
    
    1. 初始化MySQL
      [root@db01 ~ ]# cd /application/mysql/scripts/
      [root@db01 scripts]# ./mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data
    2. 启动数据库
      root@db01 scripts]# /etc/init.d/mysqld start

    3.2 Gtid 复制介绍

    1、介绍
    GTID(Global Transaction ID)是对于一个已提交事务的唯一编号,并且是一个全局(主从复制)唯一的编号。

    它的官方定义如下:
    GTID构成 = source_id :transaction_id (server_uuid 也叫 uuid,transaction_id :事务编号)
    server-uuid=880e1664-498a-11ea-87bd-000c29a94591:26

    功能:保证主从数据一致性以及主库切换更为方便。

    依赖于GTID的新功能:group commit;多线程(从库SQL);MGR

    2、什么是sever_uuid,和Server-id 区别?
    server_uuid 也叫 uuid ,默认是在第一次启动数据库时,自动生成的;删除此文件,重启数据库,会生成新的文件。
    位置:/application/mysql/data/auto.cnf
    核心特性: 全局唯一,具备幂等性:执行过的事务,不会再重复执行。

    3、GTID参数

    gtid-mode=on                        //启用gtid类型,否则就是普通的复制架构
    enforce-gtid-consistency=true               //强制GTID的一致性
    log-slave-updates=1                //slave更新是否记入日志
    

    4、GTID复制与普通复制区别
    第一次开启主从复制,IO线程读取relay-log日志,发现是空的,会读取主库二进制日志,请求所有复制。
    下次复制时,自动获取relay-log最后一条日志位置(包含GTID号),获取新的事务,不需要再读取master.info信息

    CHANGE MASTER TO
    MASTER_HOST='10.0.0.51',
    MASTER_USER='repl',
    MASTER_PASSWORD='123',
    MASTER_PORT=3307,
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=444,
    MASTER_CONNECT_RETRY=10;
    
    change master to 
    master_host='10.0.0.51',
    master_user='repl',
    master_password='123' ,
    MASTER_AUTO_POSITION=1;
    start slave;
    
    (0)在主从复制环境中,主库发生过的事务,在全局都是由唯一GTID记录的,更方便Failover
    (1)额外功能参数(3个)
    (2)change master to 的时候不再需要binlog 文件名和position号,MASTER_AUTO_POSITION=1;
    (3)在复制过程中,从库不再依赖master.info文件,而是直接读取最后一个relaylog的 GTID号
    (4) mysqldump备份时,默认会将备份中包含的事务操作,以以下方式
        SET @@GLOBAL.GTID_PURGED='8c49d7ec-7e78-11e8-9638-000c29ca725d:1';
        告诉从库,我的备份中已经有以上事务,你就不用运行了,直接从下一个GTID开始请求binlog就行。
    

    5、GTID严格要求事务的连续性,当GTID从库宕机、中断主库的复制,主库仍在发送事务,此时需要在从库提交空事务,填补空缺日志,否则无法继续复制。

    • 注入空事务的方法:
      stop slave;
      set gtid_next='880e1664-498a-11ea-87bd-000c29a94591:1-2';
      begin;
      commit;
      set gtid_next='AUTOMATIC';
      start slave;
      这里的xxxxx:N 也就是你的slave sql thread 报错的GTID ,或者说是你想要跳过的GTID.

    • 最好的解决方法:重新构建主从环境

    3.3 GTID复制配置

    前提:清理完环境,配置文件配置好,初始化数据库

    # master:
    grant replication slave  on *.* to repl@'10.0.0.%' identified by '123';
    
    # slave:
    reset maser;    //清理之前的relay-log
    change master to 
    master_host='10.0.0.51',
    master_user='repl',
    master_password='123' ,
    MASTER_AUTO_POSITION=1;
    
    start slave;
    

    3.4 查看GTID

    # 主库
     pc [(none)]>show master status;
    +------------------+----------+--------------+------------------+------------------------------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |
    +------------------+----------+--------------+------------------+------------------------------------------+
    | mysql-bin.000011 |      191 |              |                  | 880e1664-498a-11ea-87bd-000c29a94591:1-2 |
    +------------------+----------+--------------+------------------+------------------------------------------+
    1 row in set (0.00 sec)
    
    # 从库
     pc [(none)]> pc [(none)]>show slave status\G
    *************************** 1. row ***************************
                                ···
               Retrieved_Gtid_Set:                           //从库执行到的GTID号
                Executed_Gtid_Set: 880e1664-498a-11ea-87bd-000c29a94591:1-2
    
    

    相关文章

      网友评论

          本文标题:MySQL-lesson09-主从复制高级功能

          本文链接:https://www.haomeiwen.com/subject/uufuxhtx.html