加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL 8.0新特性:彻底解决困扰运维的复制延迟问题,你信吗?

发布时间:2018-09-19 06:51:03 所属栏目:MySql教程 来源:雁南归
导读:副标题#e# 技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战 MySQL 8.0可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前Generally Available版本已经已经发布,在此将介绍8.0版本中引入的一个重要的新特性基于
副标题[/!--empirenews.page--] 技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战

MySQL 8.0可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前Generally Available版本已经已经发布,在此将介绍8.0版本中引入的一个重要的新特性——基于WriteSet的并行复制方案,此方案号称是彻底解决困扰MySQL运维人员多年的复制延迟问题。

说到并行复制,这里简单的回顾一下各个版本的MySQL复制的演进,以帮助理解8.0版本中对并行复制MTS的优化。

一、MySQL主从复制模型

一切都要从MySQL的主从复制模型开始说起,下图是最经典的MySQL主从复制模型架构图:

MySQL 8.0新特性:彻底解决困扰运维的复制延迟问题,你信吗?

MySQL复制模型

MySQL的主从架构依赖于MySQL Binlog功能,Master节点上产生Binlog并将Binlog写入到Binlog文件中。

Slave节点上启动两个线程:一个IO线程,从MySQL上捞取Binlog日志并写入到本地的RelayLog日志;另一个SQL线程,不断从RelayLog日志中读取日志,并解析执行,这样通过在主机和从机上增加几个文件的顺序读写操作,就可以保证所有在主机上执行过的SQL语句都在从机上一摸一样的执行过一遍。

复制延迟,指的就是一个事务在Master执行完成以后,要多久以后才能在Slave上执行完成。

由于对Binlog文件以及RelayLog文件的读写均为顺序操作,在生产环境中,Slave上的IO线程对Binlog文件的Dump操作是很少产生延迟的。实际上,从MySQL 5.5开始,MySQL官方提供了半同步复制插件,每个事务的Binlog需要保证传输到Slave写入 RelayLog 后才能提交,这种架构在主从之间提供了数据完整性,保证了主机在发生故障后从机可以拥有完整的数据副本。因此,复制延迟通常发生在SQL线程执行的过程中。

从架构图上可以看到,最早的主从复制模型中,只有一个线程负责执行Relaylog,也就是说所有在主机上的操作,在从机上是串行回放的。这就带来一个问题,如果主上写入压力比较大,那么从上的回放速度很有可能会一直跟不上主。(除此之外,MySQL的架构决定了Binlog只有在Commit阶段才会写入Binlog文件并Dump给从机,这也导致主从事务必然有执行延迟,这个问题在大事务中体现的特别明显,不过这个问题就不在本文的讨论范围内了)

既然主从延迟的问题是单线程回放RelayLog太慢,那么减少主从延迟的方案自然就是提高从机上回放RelayLog的并行度。

二、5.7中的并行复制

1、Schema级别的并行复制

MySQL官方在5.6中引入了一个比较简单并行复制方案,其架构如下:

MySQL 8.0新特性:彻底解决困扰运维的复制延迟问题,你信吗?

(图片来自姜承尧老师的博客)

红色框部分为并行回放的关键,5.6中若开启并行回放的功能,便会启动多个WorkThread ,而原来负责回放的SQLThread会转变成Coordinator角色,负责判断事务能否并行执行并分发给WorkThread。

如果事务分别属于不同的Schema,并且不是DDL语句,同时没有跨Schema操作,那么就可以并行回放,否则需要等所有Worker线程执行完成后再执行当前日志中的内容。

这种并行回放是Schema级别的并行,如果实例上有多个Schema将会因此收益,而如果实例上只有一个Schema,那么事务将无法并行回放,而且还会因多了分发的操作导致效率略微下降。而在实际应用中,单库多表才是更常见的情况。

2、基于Group Commit的并行复制

虽然5.6中的并行复制在大多数应用场景中对回放速度的提升不大,但是该架构却成为了后来MySQL并行复制的基础——即在Slave上并行回放RelayLog,SQL线程负责判断能否并行回放,并分配给Work线程回放。

5.6 中引入Group Commit技术,是为了解决事务提交的时候需要fsync导致并发性不够而引入的。简单来说,就是由于事务提交时必须将Binlog写入到磁盘上而调用fsync,这是一个代价比较高的操作,事务并发提交的情况下,每个事务各自获取日志锁并进行fsync会导致事务实际上以串行的方式写入Binlog文件,这样就大大降低了事务提交的并发程度。

5.6中采用的Group Commit技术将事务的提交阶段分成了Flush、Sync、Commit三个阶段,每个阶段维护一个队列,并且由该队列中第一个线程负责执行该步骤,这样实际上就达到了一次可以将一批事务的Binlog fsync到磁盘的目的,这样的一批同时提交的事务称为同一个Group的事务。

Group Commit虽然是属于并行提交的技术,但是却意外解决了从机上事务并行回放的一个难题——即如何判断哪些事务可以并行回放。如果一批事务是同时Commit的,那么这些事务必然不会有互斥的持有锁,也不会有执行上的相互依赖,因此这些事务必然可以并行的回放。

因此MySQL 5.7 中引入了新的并行回放类型, 由参数 slave_parallel_type决定,默认值DATABASE将会采用5.6版本中的SCHEMA级别的并行回放,设置为LOGICAL_LOCK则会采用基于GroupCommit的并行回放,同一个Group内的事务将会在Slave上并行回放。

为了标记事务所属的组,MySQL 5.7 版本在产生 Binlog 日志时会有两个特殊的值记录在 Binlog Event 中,last_committed 和 sequence_number,其中 last_committed指的是该事务提交时,上一个事务提交的编号,sequence_number是事务提交的序列号,在一个Binlog文件内单调递增。如果两个事务的last_committed值一致,这两个事务就是在一个组内提交的。

  1. root@localhost:~# mysqlbinlog mysql-bin.0000006 | grep last_committed  
  2. #150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1  
  3. #150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2  
  4. #150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3  
  5. #150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4  
  6. #150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5  
  7. #150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6  
  8. #150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7  
  9. #150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8  
  10. #150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9  
  11. #150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10  
  12. #150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11  
  13. #150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12  
  14. #150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13 

如上binlog文件中,sequence_number 1-6的事务last_committed都是0 ,因此属于同一个组,可以在slave上并行回放,7-12的last_committed都是6,也属于同一个组,因此可以并行回放。

5.7 中引入的基于Logical_Lock极大的提高了在主机并发压力比较大的情况下从机上的回放速度,基本上做到了主机上如何提交的,在从机上如何回放。

三、MySQL MGR中的WriteSet

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读