初识MySQL与MariaDB多线程并行复制
2018-04-30 21:53:09 阿炯

本站赞助商链接,请多关照。
MySQL一般主从复制,有三个线程参与,都是单线程:Binlog Dump(主) -->IO Thread (从) --> SQL Thread(从)。在master节点上运行的binlogdump线程以及在slave节点上运行的I/O线程和SQL线程。具体如下:
1. master节点上的binlogdump线程,在slave与其正常连接的情况下,将binlog发送到slave上。

2.slave节点上的I/O线程,通过读取master节点发送的内容,并将数据复制到本地的relaylog中。

3.slave节点上的SQL线程,读取relaylog中的日志,并将其事务在本地执行。

复制出现延迟一般出在两个地方:
1)SQL线程忙不过来(可能需要应用数据量较大,可能和从库本身的一些操作有锁和资源的冲突;主库可以并发写,SQL线程不可以;主要原因)

2)网络抖动导致IO线程复制延迟(次要原因)。

Master节点的多个数据库并发进行事务提交,提交的事务根据LSN号顺序的写入binlog,slave节点通过I/O线程将master上的binlog写到本地relaylog中,在slave节点只有一个SQL线程来执行relaylog中的日志,这样很容易造成slave延迟。

MySQL从5.6开始有了SQL Thread多个的概念,可以并发还原数据,即并行复制技术。MySQL 5.6中,设置参数slave_parallel_workers = 4(>1),即可有4个SQL Thread(coordinator线程)来进行并行复制,其状态为:Waiting for an evant from Coordinator。

在MySQL5.6中,引入了并发复制,这个并发复制是数据库级别的,这意味着一个SQL线程可以处理一个数据库的连续事务,而不用等待其它数据库完成。这个版本的并发复制,可以理解成一个数据库一个SQL线程。其与并发有关的参数如下:
slave_parallel_workers           // worker 线程个数
slave-checkpoint-group           // 隔多少个事务做一次 checkpoint
slave-checkpoint-period          // 隔多长时间做一次 checkpoint
slave-pending-jobs-size-max      // 分发给worker的、处于等待状态的event的大小上限

MySQL5.6基于DATABASE级别的并发复制可以解决业务表放在不同的database下同步延迟的问题,但是在实际生产中大部分表还是放在同一个库中的,这种情况即使设置slave_parallel_workers大于0,也无法进行并发。在高并发的情况下,依然会造成主从复制延迟。其并行只是基于Schema的,也就是基于库的。如果数据库实例中存在多个Schema,这样设置对于Slave复制的速度可以有比较大的提升。通常情况下单库多表是更常见的一种情形,那基于库的并发就没有什么用。其核心思想是:不同schema下的表并发提交时的数据不会相互影响,即slave节点可以用对relay log中不同的schema各分配一个类似SQL功能的线程,来重放relay log中主库已经提交的事务,保持数据与主库一致。

在MySQL 5.7中,引入了基于组提交的并行复制(Enhanced Multi-threaded Slaves),设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。其核心思想:一个组提交的事务都是可以并行回放(配合binary log group commit);
slave机器的relay log中 last_committed相同的事务(sequence_num不同)可以并发执行。

其中,变量slave-parallel-type可以有两个值:
DATABASE 默认值,基于库的并行复制方式;
LOGICAL_CLOCK:基于组提交的并行复制方式。

MySQL 5.7开启Enhanced Multi-Threaded Slave配置:
# slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

至此,MySQL彻底解决了复制延迟问题。5.7的改进策略并发性更优,但出现大事务会拖后腿。

MySQL_MariaDB 多线程复制初探

MariaDB 在10.0.5就已经支持了并行复制的功能,即从库多线程复制的功能,MySQL最先在5.6.3中支持。目前暂时没有用MySQL5.6的版本,故暂时只对MariaDB进行一些说明,后期会对MySQL进行说明。

对于replication很多同学都已经很熟悉了,这里稍微讲下,在复制过程中有3个线程:Master上的IO线程和Slave上的IO、SQL线程,复制的原理可以自己去google搜。从库一直都是异步复制主库的,通过SHOW SLAVE STATUS 可以查看从库落后主库的时间,当然这个时间不一定准确。从库落后主库的原因很大一部分是因为程序在主库上执行SQL是多线程的,而从库复制主库却只有一个线程。在MariaDB10.0.0和MySQL5.6.3之前一直也是这样。在其之后的版本里支持了多线程复制,下面来看看如何开启,和开启之后的效果,目前只针对MariaDB。

说明:
MariaDB在配置文件的mysqld选项组中添加:
slave-parallel-threads

我手动修改成了8,该参数可以动态修改,在修改之前需要先stop slave。修改完之后的效果,可以看到复制线程有8个,说明已经开启了多线程复制的功能。

MySQL在配置文件的mysqld选项组中添加:
slave_parallel_workers

采用多个sql线程,每个sql线程处理不同的database,提高了并发性能,即使某database的某条语句暂时卡住,也不会影响到后续对其它的database进行操作。如果只有一个database要同步,那么多个sql线程也没有什么意义。

多线程复制在一定程度上解决了从库延迟主库并且很难追上的问题。

参考资料:

5.7官方文档
MySQL 多线程复制说明
MariaDB 多线程复制说明
各版本MySQL并行复制的实现及优缺点