0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL 5.7并行复制实现原理与调优

马哥Linux运维 来源:tlsa.com 2022-12-23 14:52 次阅读

MySQL 5.7并行复制时代

众所周知,MySQL的复制延迟是一直被诟病的问题之一,然而在Inside君之前的两篇博客中(1,2)中都已经提到了MySQL 5.7版本已经支持“真正”的并行复制功能,官方称为为enhanced multi-threaded slave(简称MTS),因此复制延迟问题已经得到了极大的改进,甚至在Inside君所在的网易电商应用中已经完全消除了之前延迟长达几小时的问题。然而,Inside君发现还是有很多小伙伴并不了解这个足以载入史册的“伟大”的特性,故作分享。总之,5.7版本后,复制延迟问题永不存在。

MySQL 5.6并行复制架构

诚然,MySQL 5.6版本也支持所谓的并行复制,但是其并行只是基于schema的,也就是基于库的。如果用户的MySQL数据库实例中存在多个schema,对于从机复制的速度的确可以有比较大的帮助。MySQL 5.6并行复制的架构如下所示:

325f99e0-828c-11ed-8abf-dac502259ad0.png

在上图的红色框框部分就是实现并行复制的关键所在。在MySQL 5.6版本之前,Slave服务器上有两个线程I/O线程和SQL线程。I/O线程负责接收二进制日志(更准确的说是二进制日志的event),SQL线程进行回放二进制日志。如果在MySQL 5.6版本开启并行复制功能,那么SQL线程就变为了coordinator线程,coordinator线程主要负责以前两部分的内容:

若判断可以并行执行,那么选择worker线程执行事务的二进制日志

若判断不可以并行执行,如该操作是DDL,亦或者是事务跨schema操作,则等待所有的worker线程执行完成之后,再执行当前的日志 这意味着coordinator线程并不是仅将日志发送给worker线程,自己也可以回放日志,但是所有可以并行的操作交付由worker线程完成。coordinator线程与worker是典型的生产者与消费者模型。

上述机制实现了基于schema的并行复制存在两个问题,首先是crash safe功能不好做,因为可能之后执行的事务由于并行复制的关系先完成执行,那么当发生crash的时候,这部分的处理逻辑是比较复杂的。从代码上看,5.6这里引入了Low-Water-Mark标记来解决该问题,从设计上看(WL#5569),其是希望借助于日志的幂等性来解决该问题,不过5.6的二进制日志回放还不能实现幂等性。另一个最为关键的问题是这样设计的并行复制效果并不高,如果用户实例仅有一个库,那么就无法实现并行回放,甚至性能会比原来的单线程更差。而单库多表是比多库多表更为常见的一种情形。

MySQL 5.7并行复制原理

MySQL 5.7基于组提交的并行复制

MySQL 5.7才可称为真正的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。

从MySQL官方来看,其并行复制的原本计划是支持表级的并行复制和行级的并行复制,行级的并行复制通过解析ROW格式的二进制日志的方式来完成,WL#4648。但是最终出现给小伙伴的确是在开发计划中称为:MTS: Prepared transactions slave parallel applier,可见:WL#6314。该并行复制的思想最早是由MariaDB的Kristain提出,并已在MariaDB 10中出现,相信很多选择MariaDB的小伙伴最为看重的功能之一就是并行复制。

MySQL 5.7并行复制的思想简单易懂,一言以蔽之:一个组提交的事务都是可以并行回放,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。

为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其可以配置的值有:

DATABASE:默认值,基于库的并行复制方式

LOGICAL_CLOCK:基于组提交的并行复制方式

支持并行复制的GTID

如何知道事务是否在一组中,又是一个问题,因为原版的MySQL并没有提供这样的信息。在MySQL 5.7版本中,其设计方式是将组提交的信息存放在GTID中。那么如果用户没有开启GTID功能,即将参数gtid_mode设置为OFF呢?故MySQL 5.7又引入了称之为Anonymous_Gtid的二进制日志event类型,如:

mysql>SHOWBINLOGEVENTSin'mysql-bin.000006';
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------+
|Log_name|Pos|Event_type|Server_id|End_log_pos|Info|
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------+
|mysql-bin.000006|4|Format_desc|88|123|Serverver:5.7.7-rc-debug-log,Binlogver:4|
|mysql-bin.000006|123|Previous_gtids|88|194|f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2|
|mysql-bin.000006|194|Anonymous_Gtid|88|259|SET@@SESSION.GTID_NEXT='ANONYMOUS'|
|mysql-bin.000006|259|Query|88|330|BEGIN|
|mysql-bin.000006|330|Table_map|88|373|table_id:108(aaa.t)|
|mysql-bin.000006|373|Write_rows|88|413|table_id:108flags:STMT_END_F|
.....

这意味着在MySQL 5.7版本中即使不开启GTID,每个事务开始前也是会存在一个Anonymous_Gtid,而这GTID中就存在着组提交的信息。

LOGICAL_CLOCK

然而,通过上述的SHOW BINLOG EVENTS,我们并没有发现有关组提交的任何信息。但是通过mysqlbinlog工具,用户就能发现组提交的内部信息:

root@localhost:~#mysqlbinlogmysql-bin.0000006|greplast_committed
#1505201411serverid88end_log_pos259CRC320x4ead9ad6GTIDlast_committed=0sequence_number=1
#1505201411serverid88end_log_pos1483CRC320xdf94bc85GTIDlast_committed=0sequence_number=2
#1505201411serverid88end_log_pos2708CRC320x0914697bGTIDlast_committed=0sequence_number=3
#1505201411serverid88end_log_pos3934CRC320xd9cb4a43GTIDlast_committed=0sequence_number=4
#1505201411serverid88end_log_pos5159CRC320x06a6f531GTIDlast_committed=0sequence_number=5
#1505201411serverid88end_log_pos6386CRC320xd6cae930GTIDlast_committed=0sequence_number=6
#1505201411serverid88end_log_pos7610CRC320xa1ea531cGTIDlast_committed=6sequence_number=7
...

可以发现较之原来的二进制日志内容多了last_committed和sequence_number,last_committed表示事务提交的时候,上次事务提交的编号,如果事务具有相同的last_committed,表示这些事务都在一组内,可以进行并行的回放。例如上述last_committed为0的事务有6个,表示组提交时提交了6个事务,而这6个事务在从机是可以进行并行回放的。

上述的last_committed和sequence_number代表的就是所谓的LOGICAL_CLOCK。先来看源码中对于LOGICAL_CLOCK的定义:

classLogical_clock
{
private:
int64state;
/*
Offsetissubtractedfromtheactual"absolutetime"valueat
loggingareplicationevent.Thatistheeventholdslogical
timestampsinthe"relative"format.Theyaremeaningfulonlyin
thecontextofthecurrentbinlog.
Thememberisupdated(incremented)perbinarylogrotation.
*/
int64offset;
......

state是一个自增的值,offset在每次二进制日志发生rotate时更新,记录发生rotate时的state值。其实state和offset记录的是全局的计数值,而存在二进制日志中的仅是当前文件的相对值。使用LOGICAL_CLOCK的场景如下:

classMYSQL_BIN_LOG:publicTC_LOG
{
...
public:
/*Committedtransactionstimestamp*/
Logical_clockmax_committed_transaction;
/*"Prepared"transactionstimestamp*/
Logical_clocktransaction_counter;
...

可以看到在类MYSQL_BIN_LOG中定义了两个Logical_clock的变量:

max_c ommitted_transaction:记录上次组提交时的logical_clock,代表上述mysqlbinlog中的last_committed

transaction_counter:记录当前组提交中各事务的logcial_clock,代表上述mysqlbinlog中的sequence_number

并行复制测试

下图显示了开启MTS后,slave服务器的QPS。测试的工具是sysbench的单表全update测试,测试结果显示在16个线程下的性能最好,从机的QPS可以达到25000以上,进一步增加并行执行的线程至32并没有带来更高的提升。而原单线程回放的QPS仅在4000左右,可见MySQL 5.7 MTS带来的性能提升,而由于测试的是单表,所以MySQL 5.6的MTS机制则完全无能为力了。

327667e2-828c-11ed-8abf-dac502259ad0.jpg

并行复制配置与调优

master_info_repository

开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前InnoSQL的版本中,添加了参数来控制刷新master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,Inside君推荐将master_info_repository设置为TABLE,来减小这部分的开销。

slave_parallel_workers

若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差,在Inside君的测试下还有20%左右的性能下降,如下图所示:

328569e0-828c-11ed-8abf-dac502259ad0.jpg

这里其中引入了另一个问题,如果主机上的负载不大,那么组提交的效率就不高,很有可能发生每组提交的事务数量仅有1个,那么在从机的回放时,虽然开启了并行复制,但会出现性能反而比原先的单线程还要差的现象,即延迟反而增大了。聪明的小伙伴们,有想过对这个进行优化吗?

Enhanced Multi-Threaded Slave配置

说了这么多,要开启enhanced multi-threaded slave其实很简单,只需根据如下设置:

#slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

并行复制监控 复制的监控依旧可以通过SHOW SLAVE STATUSG,但是MySQL 5.7在performance_schema架构下多了以下这些元数据表,用户可以更细力度的进行监控:

mysql>showtableslike'replication%';
+---------------------------------------------+
|Tables_in_performance_schema(replication%)|
+---------------------------------------------+
|replication_applier_configuration|
|replication_applier_status|
|replication_applier_status_by_coordinator|
|replication_applier_status_by_worker|
|replication_connection_configuration|
|replication_connection_status|
|replication_group_member_stats|
|replication_group_members|
+---------------------------------------------+
8rowsinset(0.00sec)

总结

MySQL 5.7推出的Enhanced Multi-Threaded Slave解决了困扰MySQL长达数十年的复制延迟问题,再次提醒一些无知的PostgreSQL用户,不要停留在之前对于MySQL的印象,物理复制也不一定肯定比逻辑复制有优势,而MySQL 5.7的MTS已经完全可以解决延迟问题了。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SQL
    SQL
    +关注

    关注

    1

    文章

    738

    浏览量

    43465
  • 数据库
    +关注

    关注

    7

    文章

    3591

    浏览量

    63375
  • MySQL
    +关注

    关注

    1

    文章

    775

    浏览量

    26006
收藏 人收藏

    评论

    相关推荐

    怎么简单实现由Labview读取的串口数据自增写入mysql5.7数据库中?

    怎么简单实现由Labview读取的串口数据自增写入mysql5.7数据库中? 已实现:串口数据的接收处理 mysql5.7的安装(已测试数据库正常运行) 愿付费解决此问题(QQ:8
    发表于 01-11 22:05

    MySQL零基础入门教程!

    MySQL5.7 主多从(m-s-s-s)第21节 MYSQL5.7 多极主从+multisource第22节 项目MySQL5.7 实现多极主从+multisource(1)第2
    发表于 06-17 14:54

    0基础学Mysql:mysql入门视频教程!

    的性能技术掌握基于MySQL的架构设计方案课程目录:第1节 MySQL课程介绍和MySQL的基础概念(1)第2节
    发表于 07-08 10:51

    MySQL的几种复制配置

    MySQL主从复制、主主复制、双主多从配置
    发表于 04-16 09:50

    mysql的主从复制

    mysql 主从复制
    发表于 04-28 14:30

    请教下怎么安装mysql

    libhtml-template-perl mysql-client-5.7 mysql-client-core-5.7 mysql-common mysql-server-5.7
    发表于 01-05 06:49

    虚拟机:CentOS 7安装MySQL5.7的步骤

    虚拟机:CentOS 7安装MySQL5.7的步骤
    的头像 发表于 07-02 18:00 2978次阅读

    MySQL 5.7MySQL 8.0 性能对比

    背景 测试mysql5.7mysql8.0分别在读写,选定,只写模式下不同并发时的性能(tps,qps) 最早 测试使用版本为mysql5.7.22和mysql8.0.15 sysb
    的头像 发表于 11-03 09:26 1.4w次阅读
    <b class='flag-5'>MySQL</b> <b class='flag-5'>5.7</b>与<b class='flag-5'>MySQL</b> 8.0 性能对比

    利用MySQL进行一主一从的主从复制

    本文讲述了如何使用MyBatisPlus+ShardingSphereJDBC进行读写分离,以及利用MySQL进行一主一从的主从复制
    的头像 发表于 07-28 09:47 816次阅读

    MySQL 5.6并行复制架构及并行复制原理

    ySQL 5.6版本也支持所谓的并行复制,但是其并行只是基于schema的,也就是基于库的。如果用户的MySQL数据库实例中存在多个schema,对于从机复制的速度的确可以有比较大的帮
    发表于 12-23 14:52 362次阅读

    探讨MySQL复制机制实现的方式

    MySQL Replication(主从复制)是指数据变化可以从一个MySQL Server被复制到另一个或多个MySQL Server上,
    的头像 发表于 04-12 09:29 404次阅读

    mysql如何实现主从复制的具体流程

    主从复制MySQL数据库中常用的数据复制技术之一,它的主要目的是将一个数据库服务器上的数据复制到其他服务器上,以实现数据的备份、高可用和分
    的头像 发表于 11-16 14:10 281次阅读

    mysql主从复制主要有几种模式

    MySQL主从复制MySQL数据库中常用的一种数据复制方式,用于实现数据的备份、负载均衡、故障恢复等目的。主从
    的头像 发表于 11-16 14:15 743次阅读

    mysql主从复制的原理

    MySQL主从复制是一种数据库复制技术,它允许将一个MySQL数据库的更新操作自动复制到其他MySQL
    的头像 发表于 11-16 14:18 273次阅读

    mysql主从复制 混合类型的复制

    MySQL主从复制是一种常用的数据复制技术,可以实现数据从一个MySQL服务器(主服务器)复制
    的头像 发表于 11-16 14:20 277次阅读