MySQL并行复制的深入浅出-阿里云开发者社区

开发者社区> 兰春> 正文

MySQL并行复制的深入浅出

简介: 一、并行复制的背景 首先,为什么会有并行复制这个概念呢?1. DBA都应该知道,MySQL的复制是基于binlog的。 2. MySQL复制包括两部分,IO线程 和 SQL线程。 3. IO线程主要是用于拉取接收Master传递过来的binlog,并将其写入到relay log 4. SQL线程主要负责解析relay log,并应用到slave中 5. 不管怎么说,IO和SQL线程都是单线程的,然后master却是多线程的,所以难免会有延迟,为了解决这个问题,多线程应运而生了。
+关注继续查看

一、并行复制的背景

  • 首先,为什么会有并行复制这个概念呢?
1. DBA都应该知道,MySQL的复制是基于binlog的。
2. MySQL复制包括两部分,IO线程 和 SQL线程。
3. IO线程主要是用于拉取接收Master传递过来的binlog,并将其写入到relay log
4. SQL线程主要负责解析relay log,并应用到slave中
5. 不管怎么说,IO和SQL线程都是单线程的,然后master却是多线程的,所以难免会有延迟,为了解决这个问题,多线程应运而生了。
6. IO多线程?
    6.1 IO没必要多线程,因为IO线程并不是瓶颈啊
7. SQL多线程?
    7.1 没错,目前最新的5.6,5.7,8.0 都是在SQL线程上实现了多线程,来提升slave的并发度


接下来,我们就来一窥MySQL在并行复制上的努力和成果吧

二、重点

是否能够并行,关键在于多事务之间是否有锁冲突,这是关键。 下面的并行复制原理就是在看如何让避免锁冲突

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

slave-parallel-type=DATABASE(不同库的事务,没有锁冲突)

之前说过,并行复制的目的就是要让slave尽可能的多线程跑起来,当然基于库级别的多线程也是一种方式(不同库的事务,没有锁冲突)

先说说优点: 实现相对来说简单,对用户来说使用起来也简单
再说说缺点: 由于是基于库的,那么并行的粒度非常粗,现在很多公司的架构是一库一实例,针对这样的架构,5.6的并行复制无能为力。当然还有就是主从事务的先后顺序,对于5.6也是个大问题

话不多说,来张图好了

mts_1

四、MySQL5.7 基于group commit的并行复制

slave-parallel-type=LOGICAL_CLOCK : Commit-Parent-Based模式(同一组的事务[last-commit相同],没有锁冲突. 同一组,肯定没有冲突,否则没办法成为同一组)
slave-parallel-type=LOGICAL_CLOCK : Lock-Based模式(即便不是同一组的事务,只要事务之间没有锁冲突[prepare阶段],就可以并发。 不在同一组,只要N个事务prepare阶段可以重叠,说明没有锁冲突)

group commit,之前的文章有详细描述,这里不多解释。MySQL5.7在组提交的时候,还为每一组的事务打上了标记,现在想想就是为了方便进行MTS吧。

我们先看一组binlog


last_committed=0 sequence_number=1
last_committed=1 sequence_number=2
last_committed=2 sequence_number=3
last_committed=3 sequence_number=4
last_committed=4 sequence_number=5
last_committed=4 sequence_number=6
last_committed=4 sequence_number=7
last_committed=6 sequence_number=8
last_committed=6 sequence_number=9
last_committed=9 sequence_number=10



4.1 Commit-Parent-Based模式

mts_2

4.2 Lock-Based模式

mts_3

五、MySQL8.0 基于write-set的并行复制

关于write-set的并行复制,看姜老师的这篇文章基于WRITESET的MySQL并行复制可以快速理解,再详细的自己去看源码即可

我这里简短的对里面的几个重要概论做些解读,这些是我当时理解的时候有偏差的地方

  • 如何启用write-set并行复制
MySQL 5.7.22+ 支持基于write-set的并行复制

# master
loose-binlog_transaction_dependency_tracking = WRITESET
loose-transaction_write_set_extraction = XXHASH64
binlog_transaction_dependency_history_size = 25000 #默认

#slave
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 32

  • 核心原理
# master

master端在记录binlog的last_committed方式变了
基于commit-order的方式中,last_committed表示同一组的事务拥有同一个parent_commit
基于write-set的方式中,last_committed的含义是保证冲突事务(相同记录)不能拥有同样的last_committed值

当事务每次提交时,会计算修改的每个行记录的WriteSet值,然后查找哈希表中是否已经存在有同样的WriteSet

1. 若无,WriteSet插入到哈希表,写入二进制日志的last_committed值保持不变,意味着上一个事务跟当前事务的last_committed相等,那么在slave就可以并行执行

2. 若有,更新哈希表对应的writeset的value为sequence number,并且写入到二进制日志的last_committed值也要更新为sequnce_number。意味着,相同记录(冲突事务)回放,last_committed值必然不同,必须等待之前的一条记录回放完成后才能执行


# slave

slave的逻辑跟以前一样没有变化,last_committed相同的事务可以并行执行
  • 并行复制如何备份
1. slave的顺序如果不一致,如何备份呢?

    1.1 对于non-gtid的gap情况,xtrabackup拷贝的时候应该会通过某种方式记录某一个一致点,否则无法进行change master
    1.2 对于gitd,gtid模式本身的机制就可以解决gap的问题
  • 要不要开启并行复制呢?
1. 基于order-commit的模式,本身并行复制已经很好了,如果并发量非常高,那么order-commit可以有很好的表现,如果并发量低,order-commit体现不了并行的优势。
但是大家想想,并发量低的MySQL,根本也不需要并行复制吧

2. 基于write-set的模式,这是目前并发度最高的并行复制了,基本可以解决大部分场景,如果并发量高,或者新搭建的slave需要快速追主库,这是最好的办法。

3. 单线程复制 + 安全参数双0,这种模式同样拥有不随的表现,一般压力均可应付。

以上三种情况,是目前解决延迟的最普遍的方法,目前我用的最多的是最后一种

  • 后面的事务比前面的事务先执行,有什么影响
1. slave的gtid会产生gap

2. 事务在某个时刻是不一致的,但是最终是一致的, 满足最终一致性

3. 相同记录的修改,会按照顺序执行。不同记录的修改,可以产生并行,并无数据一致性风险

总结,基本没啥影响

六、如何让slave的并行复制和master的事务执行的顺序一致呢

5.7.19 之后,可以通过设置 slave_preserve_commit_order = 1

官方解释:
For multithreaded slaves, enabling this variable ensures that transactions are externalized on the slave in the same order as they appear in the slave's relay log.
Setting this variable has no effect on slaves for which multithreading is not enabled.
All replication threads (for all replication channels if you are using multiple replication channels) must be stopped before changing this variable.
--log-bin and --log-slave-updates must be enabled on the slave.
In addition --slave-parallel-type must be set to LOGICAL_CLOCK.

Once a multithreaded slave has been started, transactions can begin to execute in parallel.
With slave_preserve_commit_order enabled, the executing thread waits until all previous transactions are committed before committing.
While the slave thread is waiting for other workers to commit their transactions it reports its status as Waiting for preceding transaction to commit.

大致实现原理就是:excecution阶段可以并行执行,binlog flush的时候,按顺序进行。 引擎层提交的时候,根据binlog_order_commit也是排队顺序完成
换句话说,如果设置了这个参数,master是怎么并行的,slave就怎么办并行

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
9961 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11568 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13718 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
11871 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
7315 0
+关注
兰春
数据库技术爱好者,专注于MySQL领域的运维与运营,擅长性能调优,系统瓶颈分析,热爱数据领域的一切
74
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载