MySQL主从复制除了(二十九)中说到的问题,还有部分是比较少见的。例如:从库的IO线程获取到主库的binlog,此时获取到的binlog在从库的Tcp/Ip缓存中,写入master.info后,还没来得及写入relay-log,从库宕机,缓存丢失,而master.info中已经有了新的position,等从库修复好,IO线程会以新的position获取binlog,那么relay-log就丢失部分日志。为了解决这一问题,MySQL有了新的机制。

半同步复制

机制:等IO线程将binlog写入relay-log后再返回ACK给主库,这样才算一次完整的binlog复制。

作用:保证主从数据一致性的问题,安全的考虑,但是消耗的时间太长,因为IO线程与主库之间形成了一个同步操作,但是SQL线程还是异步的,所以叫做半同步复制。但是性能太差,不建议使用。

发展:
        MySQL 5.5 开始出现半同步复制的特性
        MySQL 5.6 以后出现group commit 组提交功能,来提升开启版同步复制的性能
        MySQL 5.7 增强半同步复制的新特性:after sync;

操作:

  1. 加载插件
    主库:INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
    从库:INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
    查看插件是否加载成功:show plugins;
     
  2. 启动插件
    主库:SET GLOBAL rpl_semi_sync_master_enabled = 1;
    从库:SET GLOBAL rpl_semi_sync_slave_enabled = 1;
     
  3. 重启从库上的IO线程
    STOP SLAVE IO_THREAD;
    START SLAVE IO_THREAD;
     
  4. 查看是否运行:
    主库:show status like 'Rpl_semi_sync_master_status';
    从库:show status like 'Rpl_semi_sync_slave_status';

补充:
      参数:rpl_semi_sync_master_timeout   默认是10000ms (10s)
      # 默认情况先,到达10秒钟还没有ack,主从关系自动切换为普通复制
      # 如果是1主多从的半同步复制,只要有一台落地relaylog,返回ack,这次半同步就完成了。

 

延时从库

机制:会专门找一个节点,配置成延时节点,尽可能防止逻辑损坏,一般情况下这个节点会用作备份

配置:设置从库SQL_thread的延时

[root@db01 /]# mysql -S /data/3309/mysql.sock

mysql> stop slave;
Query OK, 0 rows affected (0.04 sec)

mysql> Change master to master_delay = 60;
Query OK, 0 rows affected (0.01 sec)

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

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.20
                  Master_User: repl
                      。
                      。
                   省略部分
                      。
                      。
             Master_Server_Id: 3307
                  Master_UUID: a041fce9-b4e8-11e9-be87-000c29db612a
             Master_Info_File: /data/3309/master.info
                    SQL_Delay: 60    ##延时60s

取消延时:

mysql> stop slave;
Query OK, 0 rows affected (0.20 sec)

mysql> change master to master_delay=0;
Query OK, 0 rows affected (0.12 sec)

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

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.20
                          .
                          .
                       省略部分
                          .
                          .
             Master_Server_Id: 3307
                  Master_UUID: a041fce9-b4e8-11e9-be87-000c29db612a
             Master_Info_File: /data/3309/master.info
                    SQL_Delay: 0    ## 延时为0s

 

复制过滤

机制:设置记录数据库的二进制日志的白名单和黑名单(不建议主库方使用)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000010 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

默认情况下,Binlog_Do_DB(白名单)和Binlog_Ignore_DB(黑名单)为空。
白名单:只记录白名单中列出的库的二进制日志
黑名单:不记录黑名单列出的库的二进制日志

详情信息:show slave status\G;

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.20
                  Master_User: repl
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:    #指定数据库(白名单)
          Replicate_Ignore_DB:    # 。 。 。 (黑名单)
           Replicate_Do_Table:    #指定表 (白名单)
       Replicate_Ignore_Table:    # 。 。 。 (黑名单)
      Replicate_Wild_Do_Table:    #模糊指定白名单 (设定值:db.*,db.world*等)
  Replicate_Wild_Ignore_Table:    #。。。。黑名单(*,db.*....)
                     .
                     .
                 省略部分
                     .
                     .
           Replicate_Do_Table:  
                Auto_Position: 0
1 row in set (0.00 sec)

 配置:(设置world数据库添加到白名单)

[root@db01 3309]# vim my.cnf 

[mysqld]
replicate-do-db=world  

 重启数据库服务

[root@db01 3309]# mysqladmin -S /data/3309/mysql.sock shutdown    ##关闭数据库
[root@db01 3309]# mysqld_safe --defaults-file=/data/3309/my.cnf &

连接数据库并查看 

[root@db01 3309]# mysql -S /data/3309/mysql.sock
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.20
                  Master_User: repl
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: world     #此时world已加入白名单
          Replicate_Ignore_DB: 
                     .
                     .
                 省略部分
                     .
                     .
           Replicate_Do_Table:  
                Auto_Position: 0
1 row in set (0.00 sec)

测试白名单(分别在主库中创建数据库world和world11,然后查看从库是否同步)
3307:

mysql> create database world;
Query OK, 1 row affected (0.01 sec)

mysql> create database world11;
Query OK, 1 row affected (0.00 sec)

3309:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db01               |
| fxw                |
| mysql              |
| performance_schema |
| test               |
| world              |
+--------------------+
7 rows in set (0.04 sec)

## 发现在3309中只有world,并没有world11,这就是白名单的效果。

 

GTID复制

GTID复制属于MySQL5.6 的新特性,GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。

官方定义
GTID = source_id : transaction_id  (7E11FA47-31CA-19E1-9E56-C43AA21293967:29)
每一台mysql实例中,都会有一个唯一的uuid,标识实例的唯一性(存在于auto.cnf文件中,存放在数据目录下)

重要参数:
gtid-mode=on                      --启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true                --强制GTID的一致性
log-slave-updates=1                 --是否强制刷新二进制日志

构建1主2从的GTID复制环境:
准备3台虚拟机,db01 克隆两台虚拟机环境,分别命名为db02、db03,在生产中准备3台真实的物理机,不用多实例。

要求:

  1. 主机名、IP地址
    (主库) db01:10.0.0.20/24
    (从库)db02:10.0.0.22/24
    (从库)db03:10.0.0.23/24
     
  2. 清理之前所有的3306相关数据,只保留软件
    db01:
    cd  /application/mysql/data/
    \rm -rf ./*

    db02:
    cd  /application/mysql/data/
    \rm -rf ./*

    db03:
    cd  /application/mysql/data/
    \rm -rf ./*
     
  3. 准备配置文件(请确保下面所有路径都存在,并给binlog和tmp赋权mysql.msyql)
    主库:db01
    vim /etc/my.cnf
    
    [mysqld]
    basedir=/application/mysql
    datadir=/application/mysql/data               #权限(mysql.mysql)
    socket=/application/mysql/tmp/mysql.sock      #手动创建文件夹,系统生成(文件),权限(mysql.mysql)
    log-error=/application/mysql/log/mysql.log    #手动创建(文件夹、文件)
    log_bin=/application/mysql/binlog/mysql-bin   #手动创建文件夹,系统生成文件,权限(mysql.mysql)
    binlog_format=row
    skip-name-resolve
    server-id=20
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    [client]
    socket=/application/mysql/tmp/mysql.sock      #手动创建文件夹,系统生成(文件),权限(mysql.mysql)

    从库:db02

    vim /etc/my.cnf
    
    [mysqld]
    basedir=/application/mysql
    datadir=/application/mysql/data               #权限(mysql.mysql)
    socket=/application/mysql/tmp/mysql.sock      #手动创建文件夹,系统生成(文件),权限(mysql.mysql)
    log-error=/application/mysql/log/mysql.log    #手动创建(文件夹、文件)
    log_bin=/application/mysql/binlog/mysql-bin   #手动创建文件夹,系统生成文件,权限(mysql.mysql)
    binlog_format=row
    skip-name-resolve
    server-id=22
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    [client]
    socket=/application/mysql/tmp/mysql.sock      #手动创建文件夹,系统生成(文件),权限(mysql.mysql)

    从库:db03

    vim /etc/my.cnf
    
    [mysqld]
    basedir=/application/mysql
    datadir=/application/mysql/data               #权限(mysql.mysql)
    socket=/application/mysql/tmp/mysql.sock      #手动创建文件夹,系统生成(文件),权限(mysql.mysql)
    log-error=/application/mysql/log/mysql.log    #手动创建(文件夹、文件)
    log_bin=/application/mysql/binlog/mysql-bin   #手动创建文件夹,系统生成文件,权限(mysql.mysql)
    binlog_format=row
    skip-name-resolve
    server-id=23
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    [client]
    socket=/application/mysql/tmp/mysql.sock      #手动创建文件夹,系统生成(文件),权限(mysql.mysql)

    创建binlog,log文件夹和log/mysql.log文件,并赋权 

    [root@db03 mysql]# mkdir binlog
    [root@db03 mysql]# chown -R mysql.mysql binlog/
    [root@db03 mysql]# mkdir log
    [root@db03 mysql]# touch log/mysql.log
    [root@db03 mysql]# ll
    total 92
    drwxr-xr-x  2 root  root   4096 Aug  2 12:05 bin
    drwxr-xr-x  2 mysql mysql  4096 Aug 23 16:08 binlog
    -rw-r--r--  1 root  root  17987 Mar 18  2017 COPYING
    drwxr-xr-x  5 mysql mysql  4096 Aug 23 15:55 data
    drwxr-xr-x  2 root  root   4096 Aug  2 12:04 docs
    drwxr-x---  3 root  root   4096 Aug 17 09:05 -help
    drwxr-xr-x  3 root  root   4096 Aug  2 12:04 include
    drwxr-xr-x  3 root  root   4096 Aug  2 12:04 lib
    drwxr-xr-x  2 root  root   4096 Aug 23 16:08 log
    drwxr-xr-x  4 root  root   4096 Aug  2 12:04 man
    -rw-r--r--  1 root  root    358 Aug 23 15:53 my.cnf
    -rw-r--r--  1 root  root    943 Aug 23 15:55 my-new.cnf
    drwxr-xr-x 10 root  root   4096 Aug  2 12:05 mysql-test
    -rw-r--r--  1 root  root   2496 Mar 18  2017 README
    drwxr-xr-x  2 root  root   4096 Aug  2 12:05 scripts
    drwxr-xr-x 28 root  root   4096 Aug  2 12:05 share
    drwxr-xr-x  4 root  root   4096 Aug  2 12:05 sql-bench
    drwxr-xr-x  2 root  root   4096 Aug  2 12:05 support-files
    drwxr-xr-x  2 mysql mysql  4096 Aug 23 11:11 tmp
    [root@db03 mysql]# 

     

  4. 三台节点分别初始化数据,并删除/etc/my.cnf(因为我们采用的是/application/mysql/my.cnf):

    /application/mysql/scripts/mysql_install_db --user=mysql  --basedir=/application/mysql --datadir=/application/mysql/data/ 
    rm -rf /etc/my.cnf

     

  5. 启动三个节点,并测试

    [root@db03 mysql]# service mysqld start
    Starting MySQL... SUCCESS! 
    [root@db01 mysql]# mysql -e "show variables like 'server_id'"
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | server_id     | 20    |
    +---------------+-------+

     

  6. 配置GTID复制
    主库db01,创建主从账户

    mysql> grant replication slave  on *.* to repl@'10.0.0.%' identified by '123456';
    Query OK, 0 rows affected (0.00 sec)

    从库db02/db03,设置主库信息,并启动线程。

    mysql> change master to master_host='10.0.0.20',master_user='repl',master_password='123456' ,MASTER_AUTO_POSITION=1;
    Query OK, 0 rows affected, 2 warnings (0.07 sec)
    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)

    # master_auto_position=1 表示自动匹配position号

  7. 查看状态信息

    mysql> show slave status\G;
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 10.0.0.20
                      Master_User: repl
                      Master_UUID: 551059f1-c57c-11e9-aaa0-000c29db612a
                            。
                            。
                        省略部分
                            。
                            。
               Master_SSL_Crlpath: 
               Retrieved_Gtid_Set: 551059f1-c57c-11e9-aaa0-000c29db612a:1   #复制二进制日志的位置信息
                Executed_Gtid_Set: 551059f1-c57c-11e9-aaa0-000c29db612a:1   #执行的二进制日志位置信息
                    Auto_Position: 1
    

     

最后修改于 2019-08-23 10:01:20
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇