mysql并行复制

1.为什么需要并行复制

主从复制原理图

并行复制是为了减少复制延迟时间

并行复制,指的是,

  • 在master设置组提交

  • 在slave起用多个SQL 进程回放,减小master 与 salve 之间的延迟

dc02443bed96740e215877261694a8ba

实际上就是io_thread将可以并行的操作交给work线程
从5.5到5.7,并行粒度越来越小,从库到表到行,5.7之后才最终完善

主从复制下延迟的原因:

  • 主库写binlog与dump_thread读binlog是串行的操作(5.7+dump_thread读与写binlog是并行的,组提交)
  • sql_thread回放线程只有一个;(并行复制解决)
  • 主从所在的主机硬件性能有差异;
  • 主库有大事务;

2.并行复制配置

2.1配置

主从条件下(gtid):

主库:

binlog_group_commit_sync_delay=100     
binlog_group_commit_sync_no_delay_count=10

从库:

#MUlti-thread线程配置
slave_parallel_type=logical_clock
slave_parallel_workers=8
slave_preserve_commit_order=1
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay-log-recovery = ON
log_slave_updates=1

2.2检验并行复制

#首先重启后要确保主从状态,sql和io线程都是yes
#参数配置错误会导致主从起不来,注意start slave查看报错
#查看
select * from performance_schema.replication_applier_status_by_worker\G

*************************** 1. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 1
            THREAD_ID: 27
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 2. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 2
            THREAD_ID: 28
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 3. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 3
            THREAD_ID: 30
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 4. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 4
            THREAD_ID: 32
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 5. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 5
            THREAD_ID: 33
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 6. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 6
            THREAD_ID: 34
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 7. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 7
            THREAD_ID: 35
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
*************************** 8. row ***************************
         CHANNEL_NAME:
            WORKER_ID: 8
            THREAD_ID: 36
        SERVICE_STATE: ON
LAST_SEEN_TRANSACTION:
    LAST_ERROR_NUMBER: 0
   LAST_ERROR_MESSAGE:
 LAST_ERROR_TIMESTAMP: 0000-00-00 00:00:00
8 rows in set (0.00 sec)
#开了几个work线程,就有几条记录


show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time | State                                                  | Info             |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  1 | system user |           | NULL | Connect | 1181 | Slave has read all relay log; waiting for more updates | NULL             |
|  2 | system user |           | NULL | Connect | 1181 | Waiting for master to send event                       | NULL             |
|  3 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
|  4 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
|  6 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
|  7 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
|  8 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
|  9 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
| 10 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
| 11 | system user |           | NULL | Connect | 1181 | Waiting for an event from Coordinator                  | NULL             |
| 13 | root        | localhost | NULL | Query   |    0 | starting                                               | show processlist |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
11 rows in set (0.00 sec)

2.3监控

并行复制开启后

show slave status\G

Read_Master_Log_Pos和Exec_Master_Log_Pos对比,得出差异

可以利用gtid查看对比

3.参数详解

binlog_group_commit_sync_delay

全局动态变量,单位微妙,默认0,范围:0~1000000(1秒)。

表示 binlog 提交后等待延迟多少时间再同步到磁盘,默认0 ,不延迟。当设置为 0 以上的时候,就允许多个事务的日志同时一起提交,也就是我们说的组提交。组提交是并行复制的基础,我们设置这个值的大于 0 就代表打开了组提交的功能。

binlog_group_commit_sync_no_delay_count

全局动态变量,单位个数,默认0,范围:0~1000000。

表示等待延迟提交的最大事务数,如果上面参数的时间没到,但事务数到了,则直接同步到磁盘。若 binlog_group_commit_sync_delay 没有开启,则该参数也不会开启。

例如:

binlog_group_commit_sync_delay=100     
binlog_group_commit_sync_no_delay_count=10

100微秒合并提交一次,如果不到100微秒到了10个事务也提交一次

这俩个参数是主库并行写binlog,提高主库的并行度,从库的并行复制没关系

注意它们是合起来作为一个组提交的

slave_parallel_type=logical_clock

5.7引入了新的变量slave-parallel-type,其可以配置的值有:

  • DATABASE:默认值,基于库的并行复制方式
  • LOGICAL_CLOCK:基于组提交的并行复制方式(与主库的组提交对应)

slave_parallel_workers=8

开启多个work线程并行复制

slave_parallel_workers不要设为1,否则要经过一层负载器,更慢,不如关闭

slave_preserve_commit_order

slave_preserve_commit_order 参数在多线程复制环境下,能够保证从库回放relay log事务的顺序与这些事务在relay log中的顺序完全一致,也就是与主库提交的顺序完全一致。

举个例子,开启并行复制后,如果relay log中有3个事务A,B,C,他们在relay log中的顺序是A->B->C,而它们的last_commited相同,也就是说他们可以并行回放,那么在从库上,这3个事务,提交的顺序可能就不再是A->B->C,设置slave_preserve_commit_order=ON,能够保证这3个事务,在从库回放时,仍然按照它们在relay log中的顺序来回放,保证从库回放relay log事务的顺序与主库完全相同。

slave_preserve_commit_order:

  • 作用范围:Global
  • 动态修改:Yes,修改时需要停止SQL线程
  • 默认值:OFF

该参数起作用的前提条件是开启多线程复制:

  • slave_parallel_type=LOGICAL_CLOCK
  • slave_parallel_workers>0

在 8.0.18 及之前版本,从库只有开启binlog的两个参数(log_bin,log_slave_updates),才能设置slave_preserve_commit_order=ON,而 8.0.19 版本开始,这个前提条件不再需要了。

设置slave_preserve_commit_order=ON,当一个线程等待其他线程的事务提交时,会出现一个状态信息,在一个写入量较大的主从复制集群中,在从库上执行show processlist可以看到这个状态信息,如下:
Waiting for preceding transaction to commit

注意:

ERROR 3031 (HY000): slave_preserve_commit_order is not supported unless both log_bin and log_slave_updates are enabled.

要使用它必须开启binlog和log_slave_updates
log_slave_updates=1

master_info_repository

relay_log_info_repository

master_info_repository决定了slave的master status是存储在master.info还是slave_master_info表。

master_info_repository有两个值,分别是file和table,该参数决定了slave记录master的状态,如果参数是file,就会创建master.info文件,如果参数值是table,就在mysql中创建slave_master_info的表。

开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前InnoSQL的版本中,添加了参数来控制刷新master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,Inside君推荐将master_info_repository设置为TABLE,来减小这部分的开销。

在 MySQL 5.7 中,推荐将 master-info-repositoryrelay-log-info-repository 设置为TABLE来减少开销

master_info_repository=TABLE
relay_log_info_repository=TABLE
relay-log-recovery = ON

relay_log_recovery

改参数默认是打开的,在数据库启动后立即启动自动relay log恢复,在恢复过程中,创建一个新的relay log文件,将sql线程的位置初始化到新的relay log,并将i/o线程初始化到sql线程位置。

mysql在运行过程中,从库上可能会出现意外宕机的情况,那么在从库启动后,必须能够恢复到停止之前的状态。i/o线程必须恢复到接受事务的位置,sql线程必须恢复到一致执行事务的位置。该信息传统上是存储在文件中,那么有可能存在不一致或者存在的风险,从mysql5.7开始,可以使用表来存储这些信息,并且把这些表设置为innodb引擎,通过使用事务性存储引擎,总能够恢复这个信息。可以配置参数master_info_repository=table和relay_log_info_repository=table使从库信息存储到表中。从库如何从宕机状态恢复到正确状态,取决与从库是单线程还是多线程、relay_log_recover参数的值,以及master_auto_position的使用方式。

1,单线程模式的复制(mysql5.7)

当基于gtid模式复制的时候,并且设置了master_auto_posion参数和relay_log_recover=0,使用该设置,其中relay_log_info_repository和其他变量的设置都不会影响恢复。

当基于传统模式复制的情况下,需要设置relay_log_recovery=1和relay_log_info_repository=table。

2,多线程模式的复制(5.7)

当基于gtid模式复制的时候,并且设置了master_auto_position和relay_log_recover=0,使用该配置,其relay_log_info_repository和其他变量的设置都会影响恢复。

当基于传统模式复制的时候,请设置relay_log_recover=1,sync_relay_log=1和relay_log_info_repository=table。

posted @ 2021-08-26 17:34  EverEternity  阅读(1352)  评论(0编辑  收藏  举报