深度解析MySQL主从复制

 🎬作者简介:大家好,我是小徐🥇
☁️博客首页:CSDN主页小徐的博客
🌄每日一句:好学而不勤非真好学者

📜 欢迎大家关注! ❤️

前言

看本文之前,请先了解一下binlog、redolog等,知道他们的作用及写入过程。看到这里默认大家了解以上背景了,本篇主要将MySQL主从复制的过程以及复制方式。

一、复制过程

MySQL的主从复制,是基于binlog实现的,主要过程是这样的:

c67fb99d1c814873b49ef9c209c9aff0.png

  1. 从服务器在开启主从复制后,会创建出两个线程:I/O线程和SQL线程
  2. 从服务器的!/O线程,会尝试和主服务器建立连接,相对应的,主服务中也有一个binlogdump线程,是专门来和从服务器的//O线程做交互的。
  3. 从服务器的!/O线程会告诉主服务的dump线程自己要从什么位置开始接收binlog
  4. 主服务器在更新过程中,将更改记录保存到自己的binlog中,根据不同的binlog格式,记录的内容可能不一样。
  5. 在dump线程检测到binlog变化时,会从指定位置开始读取内容,然后会被slave的I/O线程把他拉取过去。

拉的模式,从库可以自行管理同步进度和处理延迟。

6、从服务器的!/O线程接收到通知事件后,会把内容保存在relay log中。
7、从服务器还有一个SQL线程,他会不断地读取他自己的relay log中的内容,把他解析成具体的操作,然后写入到自己的数据表中。

二、复制方式

MySQL目前支持多种复制方式,其中包括了全同步复制、异步复制和半同步复制。

1、异步复制:

这是MySQL默认的复制方式,在异步复制的方式中主库在执行完事务操作以后会立刻给客户端返回。他不需要关心从库是否完成该事务的执行。
这种方式会导致一个问题,那就是当主库出现故障时,主库虽然事务执行完了,但是可能还没来得及把数据同步给从库,就挂了。那么当从库升级为主库之后,他会丢失了这次事务的变更内容。

2、全同步复制:

全同步复制的这个方式中,当主库执行完一个事务之后,他会等待所有的从库完成数据复制之后,才会给客户端反馈。这种方式安全性可以保障了,但是性能很差。如果从库比较多的话,会导致整个过程更加长。

3、半同步复制:

半同步复制是介于全同步复制和异步复制之间的一种方案。他再执行完一个事务之后,也不会立刻给客户端反馈,但是也不会等所有从库都完成事务,而是等其中一个从库完成接收到事件之后,再反馈给客户端。
在半同步复制这个方案中,会在事务提交的2阶段都完成之后,等待从库接收到binlog,然后再返回成功。

在上面这篇中我们画过的一张图,如果把半同步复制的过程也加进去,那么就会变成:

916c67102c0b43338de2a82bf06a4cfd.png

三、并行复制

在MySQL的主从复制中,我们介绍过MySQL的主从复制的原理,在复制过程中,主库的binlog会不断地同步到从库,然后从库有一个SQL线程不断地拉取并重放这些SQL语句,那么,一旦日志内容太多的话,一个线程执行就会有延迟,就会导致主从延迟。

为了降低因为这个原因导致的主从延迟,所以MySQL提供了并行复制的方案。在MySQL的多个版本中,先后推出过很多个并行复制的方案:

  • MySQL 5.6推出基于库级别的并行复制。
  • MySQL 5.7推出基于组提交的的并行复制。
  • MySQL 8.0 推出基于WRITESET的并行复制。

1、库级别并行复制

在MySQL 5.6中,并行是基于Schema的,也就是基于库的,在MySQL 5.6中,可以配置多个库并行进行复制,这意味着每个库都可以有自己的复制线程,可以并行处理来自不同库的写入。这提高了并行复制的性能和效率。
但是,其实大多数业务都是单库的,所以这种方案,在推出之后很多开发者和DBA并不买账,因为实在是太鸡肋了。

2、组提交的的并行复制

因为5.6的并行复制被很多人诟病,于是在MySQL 5.7中推出了基于组提交的的并行复制,这才是真正意义上的并行复制。

一个组中多个事务,都处于Prepare阶段之后,才会被优化成组提交。那么就意味着如果多个事务他们能在同一个组内提交,这个就说明了这个几个事务在锁上是一定是没有冲突的,

binlog_transaction_dependency_tracking= WRITESET

transaction_write_set_extraction = XXHASH64

换句话说,就是这几个事务修改的一定不是同一行记录,所以他们之间才能互不影响,同时进入Prepare阶段,并且进行组提交。

那么,没有冲突的多条SQL,是不是就可以在主备同步过程中,在备库上并行执行回放呢?
答案是可以的,因为一个组中的多条SQL之间互相不影响,谁先执行,谁后执行,结果都是一样的!
所以,这样Slave就可以用多个SQL现成来并行的执行一个组提交中的多条SQL,从而提升效率,降低主从延迟。

3、基于WRITESET的并行复制

前面的组提交大大的提升了主从复制的效率,但是他有一个特点,就是他依赖于主库的并行度,假如主库的并发比较高,那么才可以进行组提交,那么才能用到组提交的并行复制优化。

如果主库的SQL执行并没有那么频繁,那么时间间隔可能就会超过组提交的那两个参数阈值就不会进行组提交。那么复制的时候就不能用并行复制了。

MySQL 8.0为了解决这个问题,引入了基于WriteSet的并行复制,这种情况下即使主库在串行提交的事务,只有互相不冲突,在备库就可以并行回放。

开启WRITESET:

binlog_transaction_dependency_tracking=WRITESET  # COMMIT ORDER

transaction_write_set_extraction=XXHASH64

实际上Writeset是一个集合,使用的是C++STL中的set容器

std::set<uint64>write set unique;

集合中的每一个元素都是hash值,这个hash值和transaction write set extraction参数指定的算法有关(可选OFF、MURMUR32、XXHASH64,默认值 XXHASH64),其来源就是行数据的主键和唯一键。

WriteSet 是通过检测两个事务是否更新了相同的记录来判断事务能否并行回放的,因此需要在运行时保存已经提交的事务信息以记录历史事务更新了哪些行,并且在做更新的时候进行冲突检测,拿新更新的记录计算出来的hash值和retset作比较,如果不存在,那么就认为是不冲突的,这样就可以共用同一个last committed

last committed 指的是该事务提交时,上一个事务提交的编号

就这样,就能保证同一个write set中的变更都是不冲突的,那么同一个write set就可以并行的通过多个线程进行回放SQL了。

三、存在的问题

1、数据库的主从延迟问题

数据库的主从延迟是指在主从数据库复制过程中,从服务器(Slave)上的数据与主服务器(Master)上的数据之间存在的时间差或延迟。
一般来说导致主从延迟可能由多种因素引起,以下是一些常见的原因:

  1. 网络延迟:主节点和从节点之间的网络延迟导致复制延迟这是比较常见的一种情况
  2. 从节点性能问题:从服务器的性能不足也可能导致复制延迟。如果从服务器的硬件资源(CPU、内存、磁盘)不足以处理接收到的复制事件,延迟可能会增加。
  3. 复制线程不够:当从节点只有一个线程,或者线程数不够的时候,数据回放就会慢,就会导致主从节点的数据延迟。

解决方案

解决主从延迟主要有几个事情可以做:

  1. 优化网络:确保主节点和从节点之间的网络连接稳定,尽量同城或者同单元部署,减小网络延迟
  2. 提高从服务器性能:增加从服务器的硬件资源,如CPU、内存和磁盘,以提高其性能,从而更快地处理复制事件。
  3. 并行复制:借助MySQL提供的并行复制的能力,提升复制的效率,降低延迟。

  • 43
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小徐很努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值