`

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

 
阅读更多

前言

 

这篇文章花了Inside君整整3个晚上的时间,码了3000多字,可谓满满的诚意之作,献给最有品味的你们。然由于微信公众账号对于技术博文的支持并不是很友好,对于有代码洁癖的小伙伴,Inside君推荐点击下方的阅读原文来进行更好地阅读体验。

 

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并行复制的架构如下所示:

 

 

在上图的红色框框部分就是实现并行复制的关键所在。在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> SHOW BINLOG EVENTS in 'mysql-bin.000006';
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------+
| mysql-bin.000006 | 4 | Format_desc | 88 | 123 | Server ver: 5.7.7-rc-debug-log, Binlog ver: 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: 108 flags: STMT_END_F |
.....

 

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

 

LOGICAL_CLOCK

 

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

 

root@localhost:~# mysqlbinlog mysql-bin.0000006 | grep last_committed
#150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1
#150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2
#150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3
#150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4
#150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5
#150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6
#150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7
...

 

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

 

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

 

class Logical_clock
{
private:
int64 state;
/*
Offset is subtracted from the actual "absolute time" value at
logging a replication event. That is the event holds logical
timestamps in the "relative" format. They are meaningful only in
the context of the current binlog.
The member is updated (incremented) per binary log rotation.
*/

int64 offset;
......

 

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

 

class MYSQL_BIN_LOG: public TC_LOG
{
...
public:
/* Committed transactions timestamp */
Logical_clock max_committed_transaction;
/* "Prepared" transactions timestamp */
Logical_clock transaction_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机制则完全无能为力了。

 

 

并行复制配置与调优

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%左右的性能下降,如下图所示:

 

 

这里其中引入了另一个问题,如果主机上的负载不大,那么组提交的效率就不高,很有可能发生每组提交的事务数量仅有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 STATUS\G,但是MySQL 5.7在performance_schema架构下多了以下这些元数据表,用户可以更细力度的进行监控:

 

mysql> show tables like '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 |
+---------------------------------------------+
8 rows in set (0.00 sec)

 

总结

 

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

 

原文地址:http://mp.weixin.qq.com/s?__biz=MjM5MjIxNDA4NA==&mid=205236417&idx=1&sn=15281c834348911cea106478aa819175&scene=23&srcid=0525zwrE6gRYCIPgKxoq40iN#rd

 

分享到:
评论

相关推荐

    mysql-5.7版本源码包

    9. **并行复制**:MySQL 5.7的复制功能进行了改进,支持并行复制,允许多个交易同时在从库上执行,提高了复制性能。 10. **线程池插件**:为了提高多用户并发性能,5.7引入了线程池插件,减少了创建和销毁线程的...

    mysql5.7.33社区版.zip

    - **JSON 数据类型**:MySQL 5.7 引入了原生 JSON 数据类型,允许存储和查询 JSON 文档,支持 JSON 检索和操作,增强了与 NoSQL 数据库的交互能力。 - ** Spatial 数据类型**:地理空间数据类型的增强,支持更多...

    mysql5.7手册

    此“mysql5.7手册”是官方文档,详细地阐述了MySQL 5.7的各项特性、配置、操作以及最佳实践。 一、安装与配置 在MySQL 5.7中,安装过程已经变得更为简洁。文档会指导用户如何在各种操作系统上安装MySQL Server,...

    mysql-server-mysql-5.7.36.tar.gz

    9. **并行复制**:MySQL 5.7支持事务并行复制,提高了复制性能,尤其是在高并发写入的场景下。 10. **存储过程和触发器的改进**:增加了对存储过程和触发器的优化,提升了它们的性能和可靠性。 在解压`mysql-...

    MySQL 5.6-5.7姜承尧调优insidemysql_my

    例如,使用主从复制实现负载均衡,或将热点数据放在单独的表或服务器上。 6. **定期维护**:包括定期分析和优化表(ANALYZE TABLE, OPTIMIZE TABLE)、清理无用数据、监控和日志分析等,以保持数据库健康运行。 7....

    mysql5.7.zip

    MySQL 5.7引入了InnoDB存储引擎的性能改进,例如,更高效的InnoDB缓冲池、更高的并行插入速度以及对InnoDB事务的优化。此外,查询优化器也得到了增强,能更好地处理复杂的查询和联接操作。 3. **JSON支持**: ...

    mysql-5.7.30.rar

    MySQL的复制功能在5.7版本中得到了强化,支持事务并行复制,这意味着主库上的多个事务可以并行写入从库,显著提高了复制效率。 6. **安全性和权限管理**: MySQL 5.7增强了安全特性,比如默认的更安全的加密方式...

    mysql-5.7.34-1.el7.x86_64.rpm-bundle.zip

    在深入探讨 MySQL 5.7.34 的特点之前,先了解一下 RPM 包的工作原理。RPM 包包含软件的二进制文件、配置文件、文档、库依赖关系等,安装时会自动处理依赖性问题,使得安装过程简单且易于管理。".tar" 文件则是一个未...

    mysql 5.7 Percona Server

    MySQL 5.7 Percona Server 是一个针对 MySQL 数据库服务器的增强版本,旨在提供更高效、更稳定且功能丰富的数据库管理解决方案。Percona 公司是 MySQL 社区的重要贡献者,他们对 MySQL 进行了优化,尤其注重在高并发...

    1z0-888 MYSQL5.7 OCP

    标题中提到的“1z0-888 MYSQL5.7 OCP”意味着这是一个关于Oracle认证的MySQL 5.7数据库管理员的专业考试。OCP代表Oracle Certified Professional,是Oracle公司提供的专业资格认证之一,面向的是对数据库技术具备...

    mysql5.7mysql5.7mysql5.7

    而`mysql5.7.txt`可能包含了关于MySQL 5.7的安装指南、配置参数、使用技巧或其他相关文档,对于理解和使用MySQL 5.7非常有帮助。 综上所述,MySQL 5.7不仅在性能、安全性、功能性和易用性方面都有所提升,而且对...

    mysql5.7软件及配置

    6. **性能调优**:MySQL 5.7提供了一些性能优化工具,如线程池、InnoDB并行查询、查询缓存改进等。你可以通过监控性能指标,如QPS(每秒查询量)、RT(响应时间)等,来调整相关参数以提高性能。 7. **备份与恢复**...

    5.7版本MySQL的安装包

    5. **增强的复制功能**:MySQL 5.7增强了主从复制,包括半同步复制的改进和GTID(全局事务标识符)的广泛支持,确保了数据的一致性和可恢复性。 6. **安全性**:5.7版本提升了安全特性,如密码验证插件的更新,支持...

    mysql-5.7.30-el7-x86_64.tar.gz

    2. **InnoDB存储引擎**:作为MySQL的默认存储引擎,InnoDB在5.7版本中得到了显著优化,包括支持多线程并行查询,提高了大量数据插入和更新的性能。此外,还引入了自适应哈希索引,能自动创建和维护,进一步提升查询...

    mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz

    7. **组复制**:MySQL 5.7引入了组复制,这是一种高可用性解决方案,允许数据在多个服务器之间实时同步。 8. **SQL标准的增强**:支持更多的SQL标准,包括窗口函数、用户定义变量的改进和WITH语句的增强。 9. **...

    03 MySql 5.7+Navicat.zip

    1. 性能提升:MySQL 5.7引入了InnoDB存储引擎的性能优化,例如更快的插入速度、更高效的查询处理以及更好的并行处理能力。其中,InnoDB Plugin XtraDB被默认启用,提供了更高的并发性和更少的锁冲突。 2. JSON数据...

    mysql-5.7.30

    1. **性能提升**:MySQL 5.7.30 引入了InnoDB存储引擎的优化,如更快的索引插入速度,更高效的查询处理,以及对并行复制的支持,这使得大规模数据处理时的性能得到了显著提升。 2. **InnoDB增强**:InnoDB存储引擎...

    MySQL基础之MySQL 5.7 新增配置

    8. **查询分析工具**: `EXPLAIN FORMAT=JSON`命令在MySQL 5.7中被添加,它提供了更详细和结构化的查询执行计划,帮助开发者理解查询优化过程并进行性能调优。 9. **二进制日志增强**: 5.7版的二进制日志支持更高效...

    mysql-boost-5.7.33.tar.gz

    MySQL-Boost是MySQL数据库系统的一个特定版本,与Boost库集成以提供更高效的性能。这个"mysql-boost-5.7.33.tar.gz"文件是一个压缩包,包含了MySQL 5.7.33版本的源代码,适用于Linux操作系统。Boost库是一个开源C++...

    mysql 性能调优 运维

    MySQL性能调优与运维是DBA日常工作中至关重要的任务,涉及到数据库系统的稳定性和效率。以下是一些关键知识点的详细说明: 1. **热点数据导出与加载的影响**:热点数据导出是为了避免数据库重启后因预热缓存而消耗...

Global site tag (gtag.js) - Google Analytics