zoukankan      html  css  js  c++  java
  • Mysql GTID复制+半同步复制+多线程复制

    一、GTID复制

    GTID的概念是Mysql 5.6版本之后才有的

    这是官方文档的介绍,

    https://dev.mysql.com/doc/refman/5.7/en/replication-gtids-concepts.html

    GTID = source_id:transaction_id

    其实GTID是由UUID:序列号 组成,这样每一个事务在集群中都有一个唯一编号,能确定这个事务是由哪个实例执行的。

    主主搭方法参考:

    https://www.cnblogs.com/nanxiang/p/12902170.html

    在搭建完成后,需要对其中的一些参数进行调整,修改my.cnf添加如下内容

    gtid_mode=ON
    enforce-gtid-consistency=ON
    master_info_repository=TABLE 
    relay_log_info_repository=TABLE

    启动主备数据库,

    在服务器A执行, 

    mysql> create database ceshi;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> show master statusG
    *************************** 1. row ***************************
                 File: mysql-bin.000014
             Position: 321
         Binlog_Do_DB: 
     Binlog_Ignore_DB: 
    Executed_Gtid_Set: 9fef2262-97b1-11ea-92b5-000c29cd3ff3:1    #GTID编号,前边是UIID,后边的是1序列号
    1 row in set (0.00 sec)

    在服务器B执行

    mysql> show slave statusG
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.150.101
                      Master_User: replicator
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000014
              Read_Master_Log_Pos: 321
                   Relay_Log_File: host102-relay-bin.000005
                    Relay_Log_Pos: 534
            Relay_Master_Log_File: mysql-bin.000014
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                ......
                ...... #内容较多,省略部分内容
               Retrieved_Gtid_Set: 9fef2262-97b1-11ea-92b5-000c29cd3ff3:1    #代表接收到的位点
                Executed_Gtid_Set: 9fef2262-97b1-11ea-92b5-000c29cd3ff3:1    #代表目前执行到哪个位点,如果Retrieved_Gtid_Set和Executed_Gtid_Set不相等,代表有延迟。
     Auto_Position: 0   #等于0代表不自动定位GTID位点,在使用GTID复制模式下,这个值一定要为1
    Replicate_Rewrite_DB:
    Channel_Name:
    Master_TLS_Version:

    1 row in set (0.00 sec)

    主备库都要执持如下命令:

    mysql> stop slave;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> change master to master_auto_position=1;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)

    再次执行show slave statusG

    可以看到Auto_Position 值已经为1了。

    Executed_Gtid_Set: 9fef2262-97b1-11ea-92b5-000c29cd3ff3:1
                    Auto_Position: 1
             Replicate_Rewrite_DB: 
                     Channel_Name: 
               Master_TLS_Version: 
    1 row in set (0.00 sec)

    使用GTID复制会有一些限制,

    官方文档,

    https://dev.mysql.com/doc/refman/5.7/en/replication-gtids-restrictions.html

    CREATE TABLE ... SELECT语句 将不支持。

    事务、存储过程、函数、触发器内部,将不能使用CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE 创建临时表。

     sql_slave_skip_counter 跳过事务的方式将不支持。

    二、半同步复制

     如下图是半步复制流程,

    1、主库写入数据,生成binlog日志,

    2、发送到备库,

    3、本地将binlog刷盘,

    4、主库存储引擎层提交事务

    5、等待备库返回ACK确认信息,

    6、返回给客户端事务成功。

    这其中有一些问题,如果因为网络等原因,备库没有收到主库发送的binlog,但在第4步时,存储引擎已经提交了。此时宕机了,就会出现主备数据不一致的问题。

     5.7版本中新加入了无损半同步复制,如下图。

    1、主库写入数据,生成binlog日志,

    2、发送到备库,

    3、本地将binlog刷盘,

    4、等待备库返回ACK确认信息,

    5、主库存储引擎层提交事务

    6、返回给客户端事务成功。

    与之前的半同步相比,第4步和第5步互换了,要先收到备库的ACK信息,才做存储引擎层提交。

    搭建步骤:

    安装插件,

    主库需要安装semisync_master.so

    备库需要安装semisync_slave.so

    为了满足主备切换后,还能继续使用半同步,主备库都需要同时安装这两个插件。

    mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> show plugins;
    +----------------------------+----------+--------------------+--------------------+---------+
    | Name                       | Status   | Type               | Library            | License |
    +----------------------------+----------+--------------------+--------------------+---------+
    | binlog                     | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
    | mysql_native_password      | ACTIVE   | AUTHENTICATION     | NULL               | GPL     |
    | sha256_password            | ACTIVE   | AUTHENTICATION     | NULL               | GPL     |
    .....
    .....中间省略 | rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL | #可以看到状态是ACTIVE了 | rpl_semi_sync_slave | ACTIVE | REPLICATION | semisync_slave.so | GPL | #可以看到状态是ACTIVE了
    +----------------------------+----------+--------------------+--------------------+---------+ 46 rows in set (0.00 sec)

    查看一些安装插件后新增加的参数

    mysql> show global variables like '%rpl_semi%';
    +-------------------------------------------+------------+
    | Variable_name                             | Value      |
    +-------------------------------------------+------------+
    | rpl_semi_sync_master_enabled              | OFF        | #半同步复制是否开启
    | rpl_semi_sync_master_timeout              | 10000      | #半同步复制超时后转为异步复制时间(单位:毫秒)
    | rpl_semi_sync_master_trace_level          | 32         | #用于开启半同步复制模式时的调试级别,默认是32
    | rpl_semi_sync_master_wait_for_slave_count | 1          | #最少需要等到几个备库收到binlog后,主库才会提交。
    | rpl_semi_sync_master_wait_no_slave        | ON         | #是否允许master每个事务提交后都要等待slave的接收确认信号。默认为on,每一个事务都会等待。如果为off,则slave追赶上后,也不会开启半同步复制模式,需要手工开启。
    | rpl_semi_sync_master_wait_point           | AFTER_SYNC | #AFTER_SYNC:备库收到binlog,并返回ACK确认后,主库存储引擎层才做提交操作。 AFTER_COMMIT:主库存储引擎层先提交,再收到备库ACK确认,这个也是旧的半同步复制方案。
    | rpl_semi_sync_slave_enabled               | OFF        | #ON表示在slave上已经开启半同步复制模式,由于还没开启半同步复制,所以现在显示为OFF
    | rpl_semi_sync_slave_trace_level           | 32         | #用于开启半同步复制模式时的调试级别,默认是32
    +-------------------------------------------+------------+
    8 rows in set (0.01 sec)

    开启半同步复制,主备库都要执行

    mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
    Query OK, 0 rows affected (0.00 sec)

    再看下半同步复制状态

    mysql> show global variables like '%rpl_semi%';
    +-------------------------------------------+------------+
    | Variable_name                             | Value      |
    +-------------------------------------------+------------+
    | rpl_semi_sync_master_enabled              | ON         | #已经为ON
    | rpl_semi_sync_master_timeout              | 10000      |
    | rpl_semi_sync_master_trace_level          | 32         |
    | rpl_semi_sync_master_wait_for_slave_count | 1          |
    | rpl_semi_sync_master_wait_no_slave        | ON         |
    | rpl_semi_sync_master_wait_point           | AFTER_SYNC |
    | rpl_semi_sync_slave_enabled               | ON         | #已经为ON
    | rpl_semi_sync_slave_trace_level           | 32         |
    +-------------------------------------------+------------+
    8 rows in set (0.01 sec)

    虽然状态都为ON了,但是需要重启io thread线程才会生效。

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

    为了这方便以后每次启动数据库,都运行在同步复制模式下,需要将这些参数加入到my.cnf配置文件中

    plugin-load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
    rpl-semi-sync-master-enabled = 1
    rpl-semi-sync-slave-enabled = 1

    验证半同步复制实验:

    T1时间点在主库操作:

    mysql> create table t1(id int primary key);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> insert into t1 select 1;
    Query OK, 1 row affected (0.00 sec)
    Records: 1  Duplicates: 0  Warnings: 0

    T2时间点在备库操作:

    mysql> select * from t1;
    +----+
    | id |
    +----+
    |  1 |   #可以看到数据已经正常同步过来了
    +----+
    1 row in set (0.00 sec)
    
    mysql> stop slave io_thread;  #把IO_THREAD线程关掉,停止主备复制
    Query OK, 0 rows affected (0.00 sec)

    T3时间点在备库操作:

    mysql> insert into t1 select 2;
    Query OK, 1 row affected (10.01 sec)  #这条插入命令执行了10秒,一直在等备库的ACK,超过10秒就不再等了,从而半同步复制变为了异常复制。
    Records: 1  Duplicates: 0  Warnings: 0

    mysql> insert into t1 select 3; #因为处于异步复制状态了,不用再等备库的ACK,数据就直接写入了。 Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0

     介绍一些关于半步复制的状态变量

    官方文档连接:

    https://dev.mysql.com/doc/refman/5.7/en/replication-options-reference.html

    mysql> show global status like '%rpl_semi%';
    +--------------------------------------------+-------+
    | Variable_name                              | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients               | 1     | #有几个备库配置了半同步复制,如上述实验完成后,这里看到的是0,因为备库的io_thread线程停掉了,已经感知不到备库的存在了。
    | Rpl_semi_sync_master_net_avg_wait_time     | 0     |
    | Rpl_semi_sync_master_net_wait_time         | 0     |
    | Rpl_semi_sync_master_net_waits             | 5     |
    | Rpl_semi_sync_master_no_times              | 1     |
    | Rpl_semi_sync_master_no_tx                 | 2     | #显示备库确认的不成功提交数量
    | Rpl_semi_sync_master_status                | ON    | #主库是异步复制模式,还是半同步复制模式
    | Rpl_semi_sync_master_timefunc_failures     | 0     |
    | Rpl_semi_sync_master_tx_avg_wait_time      | 1685  |
    | Rpl_semi_sync_master_tx_wait_time          | 5055  |
    | Rpl_semi_sync_master_tx_waits              | 3     |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
    | Rpl_semi_sync_master_wait_sessions         | 0     |
    | Rpl_semi_sync_master_yes_tx                | 3     | #显示备库确认的成功提交数量
    | Rpl_semi_sync_slave_status                 | ON    |
    +--------------------------------------------+-------+
    15 rows in set (0.00 sec)

    三、多线程复制

    默认情况下,MYSQL的复制是单线程的,即备库的io_thread取的binlog日志,并写入到中继日志后,只有sql_thread一个线程去回放日志,

    在开启多线程复制后,SQL会变为coordinator线程,同时会有多个worker线程,

    coordinator线程主要作用是分发日志给worker线程执行,

    如果遇到大事务,coordinator线程便不再发送给worker线程执行,由自己去回放这个大事务。

    多线程复制原理基于MYSQL组提交实现,

    5.6的多线程程复制是基于库的,也就是不同库中的事务操作,可以并行回放,如果一个库中的多个事务操作,只能顺序回放。

    5.7的多线程程复制是基于事务的,一个库中的多个事务,可以实现并行回放。

    开启方法:

    mysql> show variables like 'slave_parallel%';
    +------------------------+----------+
    | Variable_name          | Value    |
    +------------------------+----------+
    | slave_parallel_type    | DATABASE |   #默认是基于库的,需要修改参数为LOGICAL_CLOCK,修改这个参数,要先停掉主从复制
    | slave_parallel_workers | 0        |
    +------------------------+----------+
    2 rows in set (0.01 sec)
    
    mysql> stop slave;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> set global slave_parallel_type='LOGICAL_CLOCK';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> set global slave_parallel_workers=4; #设置worker线程数据,配置较低选择4或8,配置较高可以配置为16
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)

    同时也要修改my.cnf配置文件,重启数据库后也能生效:

    slave_parallel_workers=4
    slave_parallel_type='LOGICAL_CLOCK'

    可以看到已经有4个worker线程了

    mysql> show processlist;
    +----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
    | Id | User        | Host      | db   | Command | Time | State                                                  | Info             |
    +----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
    |  1 | system user |           | NULL | Connect |   11 | Slave has read all relay log; waiting for more updates | NULL             |
    |  2 | system user |           | NULL | Connect |   11 | Waiting for master to send event                       | NULL             |
    |  4 | system user |           | NULL | Connect |   11 | Waiting for an event from Coordinator                  | NULL             |
    |  5 | system user |           | NULL | Connect |   11 | Waiting for an event from Coordinator                  | NULL             |
    |  6 | system user |           | NULL | Connect |   11 | Waiting for an event from Coordinator                  | NULL             |
    |  7 | system user |           | NULL | Connect |   11 | Waiting for an event from Coordinator                  | NULL             |
    |  8 | root        | localhost | NULL | Query   |    0 | starting                                               | show processlist |
    +----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
    7 rows in set (0.00 sec)
  • 相关阅读:
    cin 与 getline
    ubuntu换源
    unbuntu 安装 bochs
    np.random.randint()的返回值
    vs2019 写入访问权限冲突
    44.Android之Shape设置虚线、圆角和渐变学习
    43.Android之ListView中BaseAdapter学习
    42.Android之ListView中ArrayAdapter简单学习
    Java编程思想学习(十六) 并发编程
    Java编程思想学习(十五) 注解
  • 原文地址:https://www.cnblogs.com/nanxiang/p/12972012.html
Copyright © 2011-2022 走看看