MySQL replication 演进

MySQL replication 演进

MySQL 5.5 半同步的复制

简介

主库在执行完客户端提交的事务之后不立即返回,等待至少一个从库接收并且写入到relay log中才返回客户端,提高了数据的安全性,但是造成了一定程度的延迟,降低了数据库的性能

semi-replication

其他同步概念

  • 异步复制:MySQL默认复制方式,主库在执行完操作后立即返回,而不关心从库是否已经接受、处理,可能造成数据不一致
  • 全同步复制:主库执行完一个事务必须要等其他从库都同步完成后才返回,性能严重受损

MySQL 5.6 并行复制

简介

针对 数据库中存在多个schema,并且schema下表的数量较少,开启并行复制对速度有较大的帮助

开启后SQL线程变成coordinator线程,负责如下功能:

  • 判断可以并行执行,选择worker线程执行事务的二进制操作
  • 判断不可执行,例如操作是DDL,或者事务是跨schema操作的,等待所有的worker执行完成之后再执行当前日志

存在问题

若实例中有很少的库和较多的表,回放的效果会很差,性能甚至会比单线程较差,而单库多表是常见的情况

MySQL 5.7 组提交

简介

数据库为了保障数据的安全性,往往采用了WAL机制(Write-Ahead-Log)

  • 在对数据修改之前,必须先将为修改记录日志,保证了事务的ACID机制
  • Redo log就是WAL的一种应用,当数据库突然掉电再重新启动时,可以通过Redo log来还原数据,每次事务提交时则不需要同步刷新数据文件,只需要追加Redo log就足够了

为了保障redo log和 binlog日志的数据一致性,MySQL使用了两阶段提交:

  • prepare阶段:redo日志持久化到磁盘,并将回滚段设置为prepared状态,binlog不做任何操作
  • commit阶段:innodb释放锁,释放回滚段,binlog持久花园到磁盘,然后在innodb提交

由binlog作为事务的协调者,根据redo日志是否落盘来判断在故障发生时是重做还是回滚:

  • 异常发生后,实例重启时,如果binlog已经落盘,则提交
  • 若binlog未落盘,则事务回滚

同时为binlog增加组提交的方式,分为了三个阶段((Flush 阶段、Sync 阶段、Commit 阶段),转换为批处理操作,提高性能

流程

在MySQL中的每一个阶段都有一个队列,每一个队列都有一把锁保护,第一个进入队列的事务会成为Leader,由Leader领导所在队列中的事务,完成后通知队列内其他事务操作结束

Flush阶段

  • 获取队列中的事务组,将Redo log在prepare阶段落盘
  • 将binlog写入到文件,此时只是写入文件系统的缓存中,不保证崩溃binlog不丢失,重启后可能会回滚该组事务
  • Flush阶段的作用是提供了redo Log的组提交

Sync阶段

  • 增加一组事务中的事务的数量,提高落盘的收益,由两个指标控制落盘的时机
    • binlog_group_commit_sync_delay=N 延迟N μs后,开始事务刷盘
    • binlog_group_commit_sync_no_delay_count=N,队列中的事务达到N个,立即刷盘
  • 在这一阶段崩溃后,事务会通过Flush阶段的redo 日志重做,因为Binlog已经落盘了,
  • Sync阶段是为了支持binlog提交

Commit阶段

  • 获取队列中的事务组
  • 将Redo log中已经prepare的事务在存储引擎层提交—commit
  • Commit阶段队列的作用是承接Sync阶段的事务,完成最后的引擎提交,使得Sync可以尽早的处理下一组事务,提高效率

group-commit

注意

Group Commit虽然是属于并行提交的技术,但是却意外解决了从服务器上事务并行回放的一个难题——即如何判断哪些事务可以并行回放。

为了标记事务所属的组,MySQL5.7版本在产生Binlog日志时会有两个特殊的值记录在 Binlog Event 中,

  • last_committed: 该事务提交时,上一个事务提交的编号

  • sequence_number:事务提交的序列号,在一个Binlog文件内单调递增

如果两个事务的last_committed值一致,这两个事务就是在一个组内提交的。

存在问题

  1. 在主服务器上并行提交事务才能在从服务器上并行回放

组复制模式

简介

至少由3个节点共同组成一个数据库集群,事务的提交必须经过半数以上的节点同意后方可提交,在集群中每个节点上都维护一个数据库状态机,保证节点间事务的一致性。

基于Paxos分布式一致性算法,只要超过半数以上的节点存货就不会对数据库服务造成影响,支持两种模式:

  • 单主模式:只有一个节点可以对外提供读写事务,其他节点提供只读服务
  • 多主模式:多个节点提供对外的读写事务服务,节点间事务可能有比较大的冲突,影响性能,限制了查询语句

在MGR集群中,回访的时候可以通过并行的方式回放,使用WriteSet技术检测冲突

相较于之前的复制方案,它新增了certify模块,用于检测事务是否允许提交,是否和其他事务存在冲突,使用乐观锁来对待事务之间的冲突,执行的过程如下:

  1. 节点s1发起一个更新事务T1,同时节点s2发起更新事务T2,T1在s1本地执行完成后,将其WriteSet和版本dbv=1发送给group,T2同样如此。
  2. xcom通讯协议保证了消息的有序传送,假设先收到T1事务的请求,发现当前版本cv=1,数据更新版本dbv=1,没有冲突,完成提交cv=2
  3. 之后又收到了T2事务的certify请求,dbv=1,而当前的cv=1拒接,事务T2回滚

事务依赖关系

在MySQL8.0中提供了三种用于事务的依赖关系:

  • COMMIT_ORDERE:表示继续使用5.7中的基于组提交的方式决定事务的依赖关系(默认值);
  • WRITESET:表示使用写集合来决定事务的依赖关系;
  • WRITESET_SESSION:表示使用WriteSet来决定事务的依赖关系,但是同一个Session内的事务不会有相同的last_committed值。

MySQL采用一个vector的变量存储已经提交的事务的HASH值,所有已经提交的事务的所修改的主键和非空的UniqueKey的值经过HASH后与该vector中的值对比,由此来判断当前提交的事务是否与已经提交的事务更新了同一行,并以此确定依赖关系。

WriteSet依赖检测

MySQL会有一个变量来存储已经提交的事务HASH值,所有已经提交的事务所修改的主键(或唯一键)的值经过hash后都会与那个变量的集合进行对比,来判断改行是否与其冲突,并以此来确定依赖关系

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值