MySQL的并行复制

MySQL并行复制

一、并行复制的产生

1、MySQL5.6基于schema的并行复制

MySQL从5.6开始支持并行复制,但5.6中的并行复制只是基于schema的,也就是基于库的,比较适用于一个库中存在多个schema的场景。

2、并行复制的原理

  • 在普通的主从复制架构中,slave服务器上有两个线程:IO线程和SQL线程。IO线程负责接收master的二进制日志(准确的说是二进制日志的event),SQL线程负责应用二进制日志(准确的说是relay-log)。
  • 在MySQL5.6版本中的并行复制中(需开启并行复制功能),SQL线程变为coordinator线程,判断是否可以并发执行:
    • 如可以并行执行,选择worker线程执行二进制日志
    • 如不可并行执行,是DDL或是跨schema的操作,则等待所有的worker线程执行完成之后再执行当前日志
  • coordinator线程不仅仅可以将日志发送给worker线程,也可以回放日志,但是并行的操作都会交给worker线程来完成


MySQL的并行复制_第1张图片

3、基于schema的并行复制带来的问题

基于schema的并行复制的主要问题是对于单库多表的场景是无法实现并行回放,甚至性能还不如原来的单线程复制,而单库多表比多库多表更为常见。

二、Multi-Threaded Slave 并行复制

1、MySQL5.7基于组提交的并行复制

  • MySQL5.7的并行复制不再限制于库的并行复制。
  • 行级的并行复制通过解析row格式的二进制日志的方式来实现。
  • 原理:由于InnoDB存储引擎已经保证了同时能够进入prepare/commit阶段的事务是没有冲突的(如通过InnoDB行锁机制来保证事务的调度),因此可以认为同时进入prepare阶段的事务是可以在从库并发执行的,所以为同时进入prepare阶段的事务分配相同的序列号,拥有相同序列号的事务可以在从库并发执行。
  • 5.7中引入了slave-parallel-type参数,用来控制并发复制的方式,可用的值为DATABASE和LOGICAL_CLOCK
    • DATABASE:默认值,基于库的并行复制方式
    • LOGICAL_CLOCK:基于组提交的并行复制方式(LOGICAL_CLOCK是一个全局递增的64位长整型数字,主要通过它来判断哪些事务能够并发)

2、支持并行复制的GTID

  • 为了知道执行的事务是否在一组中,MySQL5.7中将组提交的信息存放在GTID中。但是不是所有的库都会开启GTID,所以MySQL针对下面两种情况,给出了不同的解决方法:
    • 开启了GTID时:将组提交信息存放在GTID中
    • 未开启GTID时:MySQL5.7中引入了称为Anonymous_Gtid的二进制event类型,即使没有开启GTID,每个事务开始前都会存在一个Anonymous_Gtid,其中存放着组提交的信息。
  • 可以通过show binlog events查看Anonymous_Gtid的events类型
    1
    mysql> show binlog events in 'mysql-server.000001';
    2
    +---------------------+------+----------------+-----------+-------------+---------------------------------------------+
    3
    | Log_name            | Pos  | Event_type     | Server_id | End_log_pos | Info                                        |
    4
    +---------------------+------+----------------+-----------+-------------+---------------------------------------------+
    5
    | mysql-server.000001 |    4 | Format_desc    |         1 |         123 | Server ver: 5.7.17-log, Binlog ver: 4       |
    6
    | mysql-server.000001 |  123 | Previous_gtids |         1 |         154 |                                             |
    7
    | mysql-server.000001 |  154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'        |
    8
    | mysql-server.000001 |  219 | Query          |         1 |         360 | GRANT INSERT ON `accesslog`.* TO 'test1'@'%'|
    9
    | mysql-server.000001 |  360 | Anonymous_Gtid |         1 |         425 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'        |
    10
    | mysql-server.000001 |  425 | Query          |         1 |         532 | drop database accesslog                     |
  • 通过mysqlbinlog工具可以发现组提交的内部信息
1
# mysqlbinlog mysql-bin.0000006 | grep last_committed
2
#150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1
3
#150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2
4
#150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3
5
#150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4
6
#150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5
7
#150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6
8
#150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7
9
#150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8
10
#150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9
11
#150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10
12
#150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11
13
#150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12
14
#150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13
  • 可以发现比正常的binlog内容多了last_committed和sequence_number
    • last_committed表示事务提交时,上次事务提交的编号,如果事务具有相同的laster_committed,则表示这些事务都在同一组内,可以进行并行的回放
    • last_committed和sequence_number代表的就是LOGICAL_CLOCK
      • last_committed记录了上次组提交时的LOGICAL_CLOCK
      • sequence_number记录了当前组提交中各事务的LOGICAL_CLOCK

三、并行复制配置

1、参数详解

  • master_info_repository
    • 开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。
  • slave_parallel_workers
    • 若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差

2、开启并行复制MTS(Multi-Threaded Slave)

需设置以下参数
1
slave-parallel-type=LOGICAL_CLOCK
2
slave-parallel-workers=16
3
master_info_repository=TABLE
4
relay_log_info_repository=TABLE
5
relay_log_recovery=ON

四、并行复制监控

1、通过SHOW SLAVE STATUS\G监控

并行复制依然可以通过SHOW SLAVE STATUS\G来监控

2、通过performance_schema中的元数据表监控

在5.7的performance_schema中多了以下元数据表,可以进行更仔细的监控:
1
mysql> show tables like 'replication%';
2
+---------------------------------------------+
3
| Tables_in_performance_schema (replication%) |
4
+---------------------------------------------+
5
| replication_applier_configuration |
6
| replication_applier_status |
7
| replication_applier_status_by_coordinator |
8
| replication_applier_status_by_worker |
9
| replication_connection_configuration |
10
| replication_connection_status |
11
| replication_group_member_stats |
12
| replication_group_members |
13
+---------------------------------------------+
14
8 rows in set (0.00 sec)



你可能感兴趣的:(MySQL)