阿里RDS开发专家解析MySQL各版本并行复制

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:


MySQL并行复制已经是老生常谈,我从2010年开始就着手处理线上这个问题,刚开始两三年也乐此不疲地分享。现在再提这个话题有点“炒冷饭”的感觉。然而,又把它拎出来谈,是因为有些同学觉得“5.7的并行复制终于彻底解决了复制并发性问题”。但我感觉还是有必要分析一下,这就好像大家都说没有银弹,但是又期待银弹一样。


既然要说5.7版本的并行复制,干脆顺手把各个版本的并行复制都说明一下,也好有个对比。


目录


  • 背景

  • 解决基本思路

  • MySQL5.5版本分析

  • MySQL5.6版本分析

  • MariaDB分析

  • MySQL5.7版本分析

  • 小结


一. 背景


背景就是MySQL一直以来的备库复制都是单线程apply。一句话说完,因为这几年太多这样文章了。


二. 解决的基本思路


改成多线程复制。


备库有两个线程与复制相关:io_thread 负责从主库拿binlog并写到relaylog, sql_thread 负责读relaylog并执行。



多线程的思路就是把sql_thread 变成分发线程,然后由一组worker_thread来负责执行。


几乎所有的并行复制都是这个思路,有不同的,便是sql_thread 的分发策略。



而这些策略里面又分成两类:利用传统binlog格式、修改binlog。


使用传统的binlog格式的几类,由于binlog里面的信息就那些,因此只能按照粒度来分,也就是:按库、按表、按行。


另外有两个策略是修改了binlog格式的,在binlog里面增加了别的信息,用于体现提交分组。


下面我们分别介绍几个并行复制的实现。


三. 5.5版本分析


MySQL官方5.5是不支持并行复制的。但是在阿里的业务需要并行复制的年份,还没有官方版本支持,只好自己实现。而且因从兼容性角度考虑,不修改binlog格式,所以采用的是利用传统binlog格式的改造。


阿里的版本支持两种分发策略:按表和按行。


前情说明,由于MySQLbinlog日志还有用于别的系统的要求,因此阿里的binlog格式都是row----这也给并行复制的实现减少了难度。


按表分发策略:row格式的binlog,每个DML前面都是有Table_map event的。因此很容易拿到库名/表名。一个简单的思路是,不同表的更新之间是不需要严格按照顺序的。


因此按照表名hash,hash key是 库名+表名,相同的表的更新放到同一个worker上。这样就保证同一个表的更新顺序,跟主库上是一样的。


应用场景:对于多表更新的场景效果特别好。缺点是,若是热点表更新,则本策略无效。而且由于hash表的维护,性能反而下降。


按行分发策略:row格式的binlog中,也不难拿到主键ID。 有同学说如果没有主键怎么办,答案是"走开,现在谁还没主键:)"。好吧,正经答案是没有主键就不支持这个策略。


同样的,我们认为不同行的更新,可以无序并发的。只要保证同一行的数据更新,在备库上的顺序与主库上的相同即可。

因此按照主键id hash,所以这个hash key更长,必须是 库名+表名+主键id。相同行的更新放到同一个worker上。


需要注意的是,上面的描述看上去都是对单个event的操作,实际上并不能!因为备库可能接受读,因此事务的原子性是要保证的,也就是说,对于涉及多个更新操作的事务,每次用于决策的不是一个hash key,而是一组。


应用场景:热点表更新。缺点,hash key计算冲突的代价大。尤其是大事务,计算hash key的cpu消耗大,而且耗内存。这需要业务DBA做判断得失。


四. 5.6版本分析


官方的5.6支持的是按库分发。有了上面的背景,大家就知道,这个feature出来以后,在中国并没有什么反响。


但是这个策略也要说也是有优点的:


1、对于可以按表分发的场景,可以通过将表迁到不同的库,来应用此策略,有可操作性。


2、速度更快,因为hash key就一个库名。


3、不要求binlog格式,大家知道不论是row还是statement格式,都是能够轻松获取库名的。


所以并不是完全没有用的。还是习惯问题。


五. MariaDB分析


MariaDB的并行复制策略看上去有好几个选项,然而生产上可用的也就是默认值的 CONSERVATIVE。


由于maraiaDB支持多主复制,一个domain_id字段是用来标示事务来源的。如果来自于不同的主,自然可以并行(这个其实也是通用概念,还得业务DBA自己判断)。


对于同一个主库来的binlog,用commit_id 来决定分组。


想法是这样的:在主库上同时提交的事务设置成相同的commit_id。在备库上apply时,相同的commit_id可以并行执行,因为这意味着这些事务之间是没有行冲突的(否则不可能同时提交)。


这个思路跟最初从单线程改成多线程一样,个人认为是划时代的。


但是也并没有解决了所有的问题。这个策略最怕的是,拖后腿事务。


设想一下这个场景,假设某个DB里面正在作大量小更新事务(比如每个事务更新一行),这样在备库就并行得很欢乐。


然后突然,在同一个实例,另外一个库下,或者同一个库的另外一个跟目前的更新无关的表,突然有一个delte操作删除了10w行。


delete事务在提交的时候,跟当时一起提交的事务都算同一个commit_id。假设为N.


之后的小事务更新提交组commit_id为N+1。


到备库apply时,就会发现N这个组里面,其他小事务都执行完了,线程进入空闲状态,但是不能继续执行N+1这个commit_id的事务,因为N里面还有一个大事务没有执行完成,这个我们认为是拖后腿的。


而基于传统binlog格式的上面三个策略,反而没有这个问题。只要是策略上能够判断不冲突,大事务自己有个线程跑,其他事务继续并行。


六. 5.7版本分析


MySQL官方5.7版本也是及时跟进,先引入了上述MariaDB的策略。当然从版权安全上,oracle是不会允许直接port代码的。


然后官方5.7的新版本在此之上继续优化。 


实际上按组直接分段这个策略略显粗暴。实际上事务提交并不是一个点,而是一个阶段。至少我们可以分成:准备提交、提交中、提交完成。


这三个阶段都是在事务已经完成了主要操作逻辑,进入commit状态了。


同时进入“提交中”状态的算同一个commit_id。但是实际上,在任意时刻,处于”准备提交”的事务,与“提交中”的事务,也是可以并行的。但是明显他们会被分成两个不同的commit_id。


这意味着这个策略还有提升并发度的空间。


我们来看一下两种策略的对比差别。


假设主库有如下面示意图的事务序列。每个事务提交过程看成两个阶段,prepare ... commit. 分别给不同的编号。其中commit对应的数字是自然数递增,sequence_no。而prepare是对应的数字是X+1,这个X表示的是当前已经提交完成的sequence_no。



分析:


在MariaDB的策略里面,并发执行序列如下:



每个group 执行完成后,下一个group 才可以开始。


完全执行完成的时间是每个group的最大事务时间之和,即 trx3 + trx4+trx6+trx7。


因此,如果某个group里面有一个很大的事务,则整个序列的执行时间就会被拖久。


再来看5.7的改进策略:


虽然也是group1先启动,但是在trx1完成后,trx4就可以开始执行。


同样的,trx7可以在trx4执行完成后就开始执行,与trx5和trx6并发。


因此可以说上面这个例子中,备库apply过程完全达到了主库执行的并发度。


但是对于大事务,比如trx2 commit 非常久的情况,仍然存在拖后腿的问题。


七. 小结


我们看到,就并行复制,有5种策略。


按粒度区分的三个策略,粒度从粗到细是按库、按表、按行。


这三个的对比中,并行度越来越大,额外损耗也是。无关大事务不会影响并发度。


按照commit_id 的两个策略,适用范围更广,额外消耗也低。


5.7的改进策略并发性更优。但出现大事务会拖后腿。


另外,很重要的一点,5.7的策略目的是“模拟主库并发”,所以对于主库单线程更新是无加速作用的。而基于冲突的前三个策略,若满足并发条件,会出现备库比主库执行速度快的情况。这种需求在搭备库或者延迟复制的场景中可能触发。


实际上还是老话,没有万用的策略。策略的选择取决于应用场景,这是架构师的工作之一。


Q & A
 
 

Q1:请问tps到了多少才会触发单线程复制不够用的问题?

A1:实际上单线程的能力受限非常大,尤其是备库如果也设置了双1的情况下。我们测试出来,2k/s的行更新(insert/update/delete)单线程就到顶了。


Q2:除开双1的那两个参数,还会有什么其他的办法or 思路去改进从库的同步速度么?

A2: 业界做法有:1、relay fetch。 2、合并更新relay fetch 这个搜一下就有了。 合并跟新的主要思路是,把相邻的N个事务,当做一个提交,提高提交效率。


Q3:有个问题,对于这么多的并行复制解决方案,糅合和平衡是个很大的工程,能分享一下目前的使用情况不?

A3:恩,其实我所知道的很多公司,选版本并不是因为要解决主备延迟的问题。一来是并不是大家都有备库延迟的问题。二来是大家对里面的细节了解可能还不太够,有时候就用分库给分掉了。目前在RDS里面,我们也是默认不开的,对于有延迟的实例(监控可得), 会根据实际情况选择分表或者分库。明年RDS要支持mariadb和5.7。我们就会按照延迟的情况,建议用户升级到对应的版本来解决。


Q4:经常会看到有对比pg和mysql,总是看到有人说pg好,那mysql有什么明显优于pg的地方么,在比较常见的场景下?

A4:我的建议依然是,如果你发现MySQL够用,就用MySQL,如果有需求MySQL满足不了了(比如GIS),那再考虑选择别的。因为MySQL在中国用的最多,你碰到的问题,上网基本都能搜到,你碰到的坑,很少是第一次被你碰到,会有人有经验怎么跳出来。从工程的角度来说,能够减少业务风险。


Q5:一个大事务的更新导致mariadb多源复制hunge住但单源的没有问题,这个问题可能的原因是什么?

A5:比较大的可能是锁住了。要先确认一下多源之间的数据确实是不冲突的。多源数据如果不冲突的话,得具体排查了,排查方法就是在出现被堵住的情况后,打一个pstack出来,看看除了那个大事务apply线程以外,别的线程在等什么,这只能对代码了。 


讲师介绍:林晓斌


  • 阿里云RDS数据库源码开发团队负责人。

  • 淘宝核心系统数据库组技术专家。

  • 淘宝MySQL版本的核心开发者之一


本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2016-01-21

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
6月前
|
存储 关系型数据库 MySQL
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
|
8月前
|
人工智能 API 开发者
HarmonyOS Next~鸿蒙应用框架开发实战:Ability Kit与Accessibility Kit深度解析
本书深入解析HarmonyOS应用框架开发,聚焦Ability Kit与Accessibility Kit两大核心组件。Ability Kit通过FA/PA双引擎架构实现跨设备协同,支持分布式能力开发;Accessibility Kit提供无障碍服务构建方案,优化用户体验。内容涵盖设计理念、实践案例、调试优化及未来演进方向,助力开发者打造高效、包容的分布式应用,体现HarmonyOS生态价值。
500 27
|
8月前
|
人工智能 API 语音技术
HarmonyOS Next~鸿蒙AI功能开发:Core Speech Kit与Core Vision Kit的技术解析与实践
本文深入解析鸿蒙操作系统(HarmonyOS)中的Core Speech Kit与Core Vision Kit,探讨其在AI功能开发中的核心能力与实践方法。Core Speech Kit聚焦语音交互,提供语音识别、合成等功能,支持多场景应用;Core Vision Kit专注视觉处理,涵盖人脸检测、OCR等技术。文章还分析了两者的协同应用及生态发展趋势,展望未来AI技术与鸿蒙系统结合带来的智能交互新阶段。
535 31
|
8月前
|
人工智能 小程序 前端开发
【一步步开发AI运动小程序】十九、运动识别中如何解析RGBA帧图片?
本文介绍了如何将相机抽取的RGBA帧图像解析为`.jpg`或`.png`格式,适用于体测、赛事等场景。首先讲解了RGBA图像结构,其为一维数组,每四个元素表示一个像素的颜色与透明度值。接着通过`uni.createOffscreenCanvas()`创建离屏画布以减少绘制干扰,并提供代码实现,将RGBA数据逐像素绘制到画布上生成图片。最后说明了为何不直接使用拍照API及图像转换的调用频率建议,强调应先暂存帧数据,运动结束后再进行转换和上传,以优化性能。
|
8月前
|
索引
【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
在 Flutter 开发中,AzListView 是实现字母索引分类列表的理想选择。它支持 A-Z 快速跳转、悬浮分组标题、自定义 UI 和高效性能,适用于通讯录、城市选择等场景。本文将详细解析 AzListView 的核心参数和实战示例,助你轻松实现流畅的索引列表。
395 7
|
8月前
|
数据可视化 测试技术 API
前后端分离开发:如何高效调试API?有工具 vs 无工具全解析
在前后端分离的开发模式中,API 调试的效率直接影响项目的质量和交付速度。通过本文的对比分析,我们可以看到无工具调试模式虽具备灵活性和代码复用能力,但在操作便利性和团队协作上稍显不足。而传统的外部调试工具带来了可视化、高效协作与扩展性,却可能存在工具切换带来的开发链路断层问题。Apipost-Hepler 融合了两者的优势,让开发者无需离开熟悉的 IDEA 环境,就能享受可视化调试工具的强大功能。
261 5
|
8月前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
9月前
|
存储 人工智能 程序员
通义灵码AI程序员实战:从零构建Python记账本应用的开发全解析
本文通过开发Python记账本应用的真实案例,展示通义灵码AI程序员2.0的代码生成能力。从需求分析到功能实现、界面升级及测试覆盖,AI程序员展现了需求转化、技术选型、测试驱动和代码可维护性等核心价值。文中详细解析了如何使用Python标准库和tkinter库实现命令行及图形化界面,并生成单元测试用例,确保应用的稳定性和可维护性。尽管AI工具显著提升开发效率,但用户仍需具备编程基础以进行调试和优化。
615 9
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
BioMedGPT-R1:生物医药ChatGPT诞生!蒸馏DeepSeek R1突破人类专家水平,分子解析+靶点预测一键搞定
BioMedGPT-R1 是清华大学与水木分子联合开发的多模态生物医药大模型,支持跨模态问答、药物分子理解与靶点挖掘,性能显著提升。
531 5
|
10月前
|
人工智能 监控 数据可视化
提升开发效率:看板方法的全面解析
随着软件开发复杂度提升,并行开发模式下面临资源分配不均、信息传递延迟及缺乏全局视图等瓶颈问题。看板工具通过任务状态实时可视化、流量效率监控和任务依赖管理,帮助团队直观展示和解决这些瓶颈。未来,结合AI预测和自动化优化,看板工具将更高效地支持并行开发,成为驱动协作与创新的核心支柱。

推荐镜像

更多