MySQL并行复制的深入浅出
一、并行复制的背景
- 首先,为什么会有并行复制这个概念呢?
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也是个大问题
话不多说,来张图好了
四、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模式
4.2 Lock-Based模式
五、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就怎么办并行

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
等重构完这系统,我就辞职
Part.1 为什么程序员一言不合就重构代码? 当你看到前任写成一团毛球的代码块;新增几行代码需先捋半天逻辑的超级大函数;好不容易在迷宫里找到方向,小心翼翼地添加上新代码,却将别的调用系统给弄垮时;还有运行缓慢的老系统…… 此时程序员只有两个选择:要么忍,要么重构。 忍是有极限的,重构的“三次法则”表示:程序员第一次看到乱代码可以绕过去,先将手上的代码堆好;第二次再碰上这块,心里虽反感但再一次勉强绕过;第三次肯定忍不住动手。 以下的场景是不是很熟悉: 测试:这么小的功能,你为什么改动300多个文件? 开发:嘿嘿嘿,我顺便将老代码挪了地方。 测试:你知道这给我增加多少测试工作量吗?那些我都得回归一遍。 开发:不用测试,没有风险的,我就整理下代码。 测试:你上次也这么说,结果偷偷改了某接口,影响到下游系统。还有那次啊你…… 产品:你又在弄重构?我这还有一大堆需求没人开发。 开发:我这的重构系统也非常重要的。 产品:哪里重要了?你浪费这么多人力重构,用户也看不出来系统有什么变化,搞不好还弄坏老功能。求求你别重构了。 开发:我…… 虽然重构不被其他角色认可,但你的程序...
- 下一篇
MySQL复制延迟优化的方法论
一、MySQL为什么会延迟 数据延迟: 是指master执行了N个事务,slave却只执行了N-M个事务,说明master和slave之间产生了延迟 延迟原因:延迟的原因很多种,大部分情况下是 slave的处理能力跟不上master导致 接下来,我们从各种角度分析下延迟的原因 1.1 MySQL复制的架构 通过架构图,可以直观的看到数据延迟的点有哪些,当然也就可以知道如何优化了 1.2 大事务导致的延迟 大家都知道,binlog的写入时机是在commit的时候,redo的写入时机是在事务执行阶段就开始。 Oracle是通过物理复制,我们姑且认为是redo的复制,因为redo是事务执行阶段就开始写入的,所以,oracle的复制几乎没有延迟 MySQL是基于binlog复制的,如果有一个非常大的事务,如果需要1个小时,那么master在1小时候后才会生成binlog,而此时,slave就比master慢了至少1个小时,还不算是binlog传输时间 这是第一种延迟原因,破解方法后面说 PS: DDL虽然不是事务,但是特性跟大事务一样,都是在master上执行了一个巨大无比的操作才写的binl...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程