MySQL主从复制(三):主从延迟

news2024/12/24 10:35:50

主备流程图:

谈到主备的复制能力,要关注的是上图中的两个黑色箭头。

一个箭头代表了客户端写入主库,另一个箭头代表的是sql_thread执行中转日志(relay log)。如果用箭头的粗细来代表并行度的话,那么真实情况就如图所示,第一个箭头要明显粗于第二个箭头。

1)在主库上,影响并发度的原因就是各种锁了。由于InnoDB引擎支持行锁, 除了所有并发事务都在更新同一行(热点行) 这种极端场景外, 它对业务并发度的支持还是很友好的。 所以, 你在性能测试的时候会发现, 并发压测线程32就比单线程时, 总体吞吐量高。

2)日志在备库上的执行, 就是图中备库上sql_thread更新数据(DATA)的逻辑。 如果是用单线程的话, 就会导致备库应用日志不够快, 造成主备延迟。

注:在官方的5.6版本之前, MySQL只支持单线程复制, 由此在主库并发高、 TPS高时就会出现严重的主备延迟问题。

备库多线程复制机制,都是要把上图中的sql_thread,拆成多个线程,也就是都符合下面的这个模型:

上图中,coordinator就是原来的sql_thread, 不过现在它不再直接更新数据了, 只负责读取中转日志和分发事务。 真正更新日志的, 变成了worker线程。 而work线程的个数, 就是由参数slave_parallel_workers决定的。

注:参数slave_parallel_workers的值,设置为8~16之间最好(32核物理机的情况) , 毕竟备库还有可能要提供读查询, 不能把CPU都吃光了。

问1:事务能不能按照轮询的方式分发给各个worker, 也就是第一个事务分给worker_1, 第二个事务发给worker_2呢?

答:不行。因为, 事务被分发给worker以后, 不同的worker就独立执行了。 但是, 由于CPU的调度策略, 很可能第二个事务最终比第一个事务先执行。 而如果这时候刚好这两个事务更新的是同一行, 也就意味着, 同一行上的两个事务, 在主库和备库上的执行顺序相反, 会导致主备不一致的问题。

问2:同一个事务的多个更新语句, 能不能分给不同的worker来执行呢?

答:不行。举个例子, 一个事务更新了表t1和表t2中的各一行, 如果这两条更新语句被分到不同worker的话, 虽然最终的结果是主备一致的, 但如果表t1执行完成的瞬间, 备库上有一个查询, 就会看到这个事务“更新了一半的结果”, 破坏了事务逻辑的隔离性。

所以, coordinator在分发的时候, 需要满足以下这两个基本要求:

1)不能造成更新覆盖。 这就要求更新同一行的两个事务, 必须被分发到同一个worker中。

2)同一个事务不能被拆开, 必须放到同一个worker中。

MySQL 5.5版本的并行复制策略


官方MySQL 5.5版本是不支持并行复制的。

常见并行策略:按表分发策略和按行分发策略。

按表分发策略

按表分发事务的基本思路:如果两个事务更新不同的表,它们就可以并行。因为数据是存储在表里的,所以按表分发,可以保证两个worker不会更新同一行。

当然如果有跨表的事务,还是要把两张表放在一起考虑,以保证事务逻辑的隔离性。按表分发规则如下:

从上图可以看到, 每个worker线程对应一个hash表, 用于保存当前正在这个worker的“执行队列”里的事务所涉及的表。 hash表的key是“库名.表名”, value是一个数字, 表示队列中有多少个事务修改这个表。

在有事务分配给worker时, 事务里面涉及的表会被加到对应的hash表中。 worker执行完成后, 这个表会被从hash表中去掉。

图3中, hash_table_1表示, 现在worker_1的“待执行事务队列”里, 有4个事务涉及到db1.t1表,有1个事务涉及到db2.t2表; hash_table_2表示, 现在worker_2中有一个事务会更新到表t3的数据。

假设在图中的情况下, coordinator从中转日志中读入一个新事务T, 这个事务修改的行涉及到表t1和t3。

现在用事务T的分配流程,看一下基于表的分配规则:

1)由于事务T中涉及修改表t1, 而worker_1队列中有事务在修改表t1, 事务T和队列中的某个事务要修改同一个表的数据, 这种情况我们说事务T和worker_1是冲突的。

2)按照这个逻辑, 顺序判断事务T和每个worker队列的冲突关系, 会发现事务T跟worker_2也冲突。

3)事务T跟多于一个worker冲突, coordinator线程就进入等待。

4)每个worker继续执行, 同时修改hash_table。 假设hash_table_2里面涉及到修改表t3的事务先执行完成, 就会从hash_table_2中把db1.t3这一项去掉。

5)这样coordinator会发现跟事务T冲突的worker只有worker_1了, 因此就把它分配给worker_1。

6)coordinator继续读下一个中转日志, 继续分配事务。

每个事务在分发的时候, 跟所有worker的冲突关系包括以下三种情况:

1)如果跟所有worker都不冲突, coordinator线程就会把这个事务分配给最空闲的woker。

2)如果只跟一个worker冲突, coordinator线程就会把这个事务分配给这个存在冲突关系的worker。

3)如果跟多于一个worker冲突, coordinator线程就进入等待状态, 直到和这个事务存在冲突关系的worker只剩下1个。

注:按表分发的方案, 在多个表负载均匀的场景里应用效果很好。 但是, 如果碰到热点表, 比如所有的更新事务都会涉及到某一个表的时候, 所有事务都会被分配到同一个worker中, 就变成单线程复制了。

按行分发策略

要解决热点表的并行复制问题, 就需要一个按行并行复制的方案。

按行复制的核心思路是: 如果两个事务没有更新相同的行, 它们在备库上可以并行执行。 显然, 这个模式要求binlog格式必须是row。

按行复制和按表复制的数据结构差不多, 也是为每个worker, 分配一个hash表。 只是要实现按行分发, 这时候的key, 就必须是“库名+表名+唯一键的值”。

但是, 这个“唯一键”只有主键id还是不够的, 我们还需要考虑下面这种场景, 表t1中除了主键,还有唯一索引a:

CREATE TABLE `t1` (
 `id` int(11) NOT NULL,
 `a` int(11) DEFAULT NULL,
 `b` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB;

insert into t1values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5);

假设, 接下来我们要在主库执行这两个事务:

这两个事务要更新的行的主键值不同, 但是如果它们被分到不同的worker, 就有可能session B的语句先执行。 这时候id=1的行的a的值还是1, 就会报唯一键冲突。

因此, 基于行的策略, 事务hash表中还需要考虑唯一键, 即key应该是“库名+表名+索引a的名字+a的值”。

比如, 在上面这个例子中, 我要在表t1上执行update t1 set a=1 where id=2语句, 在binlog里面记录了整行的数据修改前各个字段的值, 和修改后各个字段的值。

因此, coordinator在解析这个语句的binlog的时候, 这个事务的hash表就有三个项:

1)key=hash_func(db1+t1+“PRIMARY”+2), value=2; 这里value=2是因为修改前后的行id值不变, 出现了两次。

2)key=hash_func(db1+t1+“a”+2), value=1, 表示会影响到这个表a=2的行。

3)key=hash_func(db1+t1+“a”+1), value=1, 表示会影响到这个表a=1的行。

相比于按表并行分发策略, 按行并行策略在决定线程分发的时候, 需要消耗更多的计算资源。 你可能也发现了, 这两个方案其实都有一些约束条件:

1)要能够从binlog里面解析出表名、 主键值和唯一索引的值。 也就是说, 主库的binlog格式必须是row。

2)表必须有主键。

3)不能有外键。 表上如果有外键, 级联更新的行不会记录在binlog中, 这样冲突检测就不准确。

对比按表分发和按行分发这两个方案的话, 按行分发策略的并行度更高。 不过, 如果是要操作很多行的大事务的话, 按行分发的策略有两个问题:

1)耗费内存。 比如一个语句要删除100万行数据, 这时候hash表就要记录100万个项。

2)耗费CPU。 解析binlog, 然后计算hash值, 对于大事务, 这个成本还是很高的。

所以, 在实现这个策略的时候会设置一个阈值, 单个事务如果超过设置的行数阈值(比如, 如果单个事务更新的行数超过10万行) , 就暂时退化为单线程模式, 退化过程的逻辑大概是这样的:

1)coordinator暂时先hold住这个事务。

2)等待所有worker都执行完成, 变成空队列。

3)coordinator直接执行这个事务。

4)恢复并行模式。

注:上述按表分发策略和按行分发策略是MySQL45讲作者自主研发。

MySQL 5.6版本的并行复制策略


官方MySQL5.6版本, 支持了并行复制, 只是支持的粒度是按库并行。

与按表分发策略和按行分发策略同理,按库分发策略的hash表里,key就是数据库名。

这个策略的并行效果,取决于压力模型。如果在主库上有多个DB,并且各个DB的压力均衡,使用该策略的效果会很好。

相比于按表和按行分发,按库分发策略有两个优势:

1)构造hash值的时候很快, 只需要库名; 而且一个实例上DB数也不会很多, 不会出现需要构造100万个项这种情况。

2)不要求binlog的格式。 因为statement格式的binlog也可以很容易拿到库名。

注1:如果主库上的表都放在同一个DB里面,这个策略就没有效果了。

注2:如果不同DB的热点不同,该策略也起不到并行的效果。如,一个是业务逻辑库,一个是系统配置库。

注3:理论上可以创建不同的DB, 把相同热度的表均匀分到这些不同的DB中, 强行使用这个策略。但由于需要特地移动数据, 所以这个策略用得并不多。

MariaDB的并行复制策略


MariaDB的并行复制策略特性:

1)能够在同一组里提交的事务, 一定不会修改同一行。

2)主库上可以并行执行的事务, 备库上也一定是可以并行执行的。

在实现上, MariaDB是这么做的:

1)在一组里面一起提交的事务, 有一个相同的commit_id, 下一组就是commit_id+1。

2)commit_id直接写到binlog里面。

3)传到备库应用的时候, 相同commit_id的事务分发到多个worker执行。

4)这一组全部执行完成后, coordinator再去取下一批。

MariaDB的并行复制策略缺点:

1)它并没有实现“真正的模拟主库并发度”这个目标。 在主库上, 一组事务在commit的时候, 下一组事务是同时处于“执行中”状态的。

假设了三组事务在主库的执行情况, 你可以看到在trx1、 trx2和trx3提交的时候, trx4、 trx5和trx6是在执行的。 这样, 在第一组事务提交完成的时候, 下一组事务很快就会进入commit状态。主库并行事务执行效果:

2)并行过程中,如果同组有大事务,则需要等待大事务执行完成后才能继续。即容易被大事务推后退。

按照MariaDB的并行复制策略, 备库上的执行效果:

可以看到, 在备库上执行的时候, 要等第一组事务完全执行完成后, 第二组事务才能开始执行,这样系统的吞吐量就不够。

MySQL 5.7的并行复制策略


在MariaDB并行复制实现之后, 官方的MySQL5.7版本也提供了类似的功能, 由参数slaveparallel-type来控制并行复制策略:

1)配置为DATABASE, 表示使用MySQL 5.6版本的按库并行策略。

2)配置为 LOGICAL_CLOCK, 表示的就是类似MariaDB的策略。 不过, MySQL 5.7这个策略, 针对并行度做了优化。 这个优化的思路也很有趣儿。

问:同时处于“执行状态”的所有事务,是否可以并行?

答:不能。因为, 这里面可能有由于锁冲突而处于锁等待状态的事务。 如果这些事务在备库上被分配到不同的worker, 就会出现备库跟主库不一致的情况。但所有处于“commit状态”的事务是可以并行的,因为事务处于commit状态,表示已经通过了锁冲突的检验了。

其实, 不用等到commit阶段, 只要能够到达redo log prepare阶段, 就表示事务已经通过锁冲突的检验了。两阶段提交流程图:

因此, MySQL 5.7并行复制策略的思想是:

1)同时处于prepare状态的事务, 在备库执行时是可以并行的。

2)处于prepare状态的事务, 与处于commit状态的事务之间, 在备库执行时也是可以并行的。

讲binlog的组提交的时候, 介绍过两个参数:

  • binlog_group_commit_sync_delay参数, 表示延迟多少微秒后才调用fsync。
  • binlog_group_commit_sync_no_delay_count参数, 表示累积多少个事务以后才调用fsync。

这两个参数是用于故意拉长binlog从write到fsync的时间, 以此减少binlog的写盘次数。 在MySQL 5.7的并行复制策略里, 它们可以用来制造更多的“同时处于prepare阶段的事务”。 这样就增加了备库复制的并行度。

也就是说, 这两个参数, 既可以“故意”让主库提交得慢些, 又可以让备库执行得快些。 在MySQL 5.7处理备库延迟的时候, 可以考虑调整这两个参数值, 来达到提升备库复制并发度的目的。

MySQL 5.7.22的并行复制策略


在2018年4月份发布的MySQL 5.7.22版本里, MySQL增加了一个新的并行复制策略, 基于WRITESET的并行复制。

相应地, 新增了一个参数binlog-transaction-dependency-tracking, 用来控制是否启用这个新策略。 这个参数的可选值有以下三种:

  • COMMIT_ORDER, 表示的就是前面介绍的, 根据同时进入prepare和commit来判断是否可以并行的策略。
  • WRITESET, 表示的是对于事务涉及更新的每一行, 计算出这一行的hash值, 组成集合writeset。 如果两个事务没有操作相同的行, 也就是说它们的writeset没有交集, 就可以并行。
  • WRITESET_SESSION, 是在WRITESET的基础上多了一个约束, 即在主库上同一个线程先后执行的两个事务, 在备库执行的时候, 要保证相同的先后顺序。

注:为了唯一标识, 这个hash值是通过“库名+表名+索引名+值”计算出来的。 如果一个表上除了有主键索引外, 还有其他唯一索引, 那么对于每个唯一索引, insert语句对应的writeset就要多增加一个hash值。

虽然这和前面介绍的MySQL 5.5版本的按行分发的策略是差不多的。但MySQL官方的这个实现还是有很大的优势:

1)writeset是在主库生成后直接写入到binlog里面的, 这样在备库执行的时候, 不需要解析binlog内容(event里的行数据) , 节省了很多计算量。

2)不需要把整个事务的binlog都扫一遍才能决定分发到哪个worker, 更省内存。

3)由于备库的分发策略不依赖于binlog内容, 所以binlog是statement格式也是可以的。

注1:对于“表上没主键”和“外键约束”的场景, WRITESET策略也是没法并行的, 也会暂时退化为单线程模型。

注2:大事务不仅会影响到主库,也是造成备库复制延迟的主要原因之一。因此, 在平时的开发工作中, 我建议你尽量减少大事务操作, 把大事务拆成小事务。

小结:思考题


思考:假设一个MySQL 5.7.22版本的主库, 单线程插入了很多数据, 过了3个小时后, 我们要给这个主库搭建一个相同版本的备库。这时候, 你为了更快地让备库追上主库, 要开并行复制。 在binlog-transaction-dependencytracking参数的COMMIT_ORDER、 WRITESET和WRITE_SESSION这三个取值中, 你会选择哪一个呢?你选择的原因是什么? 如果设置另外两个参数, 你认为会出现什么现象呢?

答:选择WRITESET策略。

1)由于主库是单线程压力模式, 所以每个事务的commit_id都不同, 那么设置为COMMIT_ORDER模式的话, 从库也只能单线程执行。

2)WRITESET模式通过对比更新的事务是否存在冲突的行,可以并发执行。

3)由于WRITESET_SESSION模式要求在备库应用日志的时候, 同一个线程的日志必须与主库上执行的先后顺序相同, 也会导致主库单线程压力模式下退化成单线程复制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1688646.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring-boot集成slf4j(二)logback配置详解

一、configuration 根节点:configuration,作为顶级标签, 可以用来配置一些lockback的全局属性,常见的属性如下: (1)scan“true” :scan是否开启自动扫描,监控配置文件更…

【Crypto】看我回旋踢

文章目录 一、看我回旋踢二、知识点什么是ROT13?工作原理分析字符串格式 解题感悟 一、看我回旋踢 关键词回旋,盲猜ROT13 因为以 synt{ 开头,并以 } 结束,基本可以判断是ROT13 小小flag,拿下! 二、知识点 …

Algoriddim djay Pro Ai for Mac:AI引领,混音新篇章

当AI遇上音乐,会碰撞出怎样的火花?Algoriddim djay Pro Ai for Mac给出了答案。这款专业的DJ混音软件,以AI为引擎,引领我们进入混音的新篇章。 djay Pro Ai for Mac的智能混音功能,让每一位DJ都能感受到前所未有的创作…

LAMDA面试准备(2024-05-23)

有没有学习过机器学习,提问了 FP-Growth 相比 Apriori 的优点 1. 更高的效率和更少的计算量(时间) FP-Growth 通过构建和遍历 FP-树 (Frequent Pattern Tree) 来挖掘频繁项集,而不需要像 Apriori 那样生成和测试大量的候选项集。具…

GQL 来了!ISO/IEC 正式发布 GQL 数据库国际标准!

历时四年筹备,超过20个国家的标准和技术专家参与制定,ISO/IEC GQL (图查询语言)标准于2024年4月12日正式发布! 作为国际标准化组织(ISO)继 1987年 发布SQL后,唯一发布的数据库查询语…

数据库迁移——kettle开发01

背景:数据库的多种多样,在搭建项目之初,并没有详细考虑到数据库的建设,当增加配置不能满足业务场景需要时,这时候考虑到使用更高性能的数据库,如将MySQL更换为oracle数据库。或者在搭建新项目时&#xff0c…

【EXCEL_VBA_基础知识】08 在VBA中使用公式 ※

课程来源:王佩丰老师的《王佩丰学VBA视频教程》,如有侵权,请联系删除! 目录 1. 函数在哪找? 1.1 工作表函数(Application.WorksheetFunction.func) 1.2 VBA函数 2. 常用VBA变量 3. 函数应用…

如何做好云安全防护

随着云计算技术的迅猛发展和普及,越来越多的企业和个人选择将数据和业务应用迁移到云平台,以享受其带来的高效、便捷和可扩展性。然而,云环境的复杂性和开放性也带来了前所未有的安全挑战。如何确保云环境中的数据安全,成为了每一…

瑞米派Ubuntu系统移植指南-米尔RemiPi

1.概述 Linux系统平台上有许多开源的系统构建框架,这些框架方便了开发者进行嵌入式系统的构建和定制化开发,目前比较常见的有Buildroot, Yocto, OpenEmbedded等等。 同时更多的传统的桌面系统也加入到嵌入式环境体系中,如Ubuntu&#xff0c…

微信小程序使用input标签遇到的问题

场景1&#xff1a;多个input标签切换无法聚焦问题 解决方案1&#xff1a; 在网上搜的用官方给的always-embed属性&#xff0c;但是也明确标注了只有ios可用 解决方案2&#xff1a; 使用focus属性&#xff1a;每次点击input标签都重新设置 wxml: <input adjust-position…

一文带你了解所有常用排序算法

目录 快速排序 堆排序 桶排序 归并排序 拓扑排序 本文主要介绍那些我在刷题过程中常用到的排序算法: 快速排序,堆排序,桶排序,归并排序,拓扑排序 其余算法例如冒泡,插入这种效率特别低的算法就不介绍了,用的可能性极小 每一个算法都将采用例题加解释的方式进行介绍 快速…

文心智能体应用示例:职场反PUA专家的诞生

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

LangChain llamaindex

LangChain 参考&#xff1a; 全流程 | Windows 系统本地部署开源模型阿里通义千问 QWEN 1.5&#xff0c;结合 LangChain-Chatchat 框架和向量数据库 FAISS、Milvus - 知乎

蓝桥杯-数三角(ac代码时间复杂度分析)

问题描述 小明在二维坐标系中放置了 ( n ) 个点&#xff0c;他想在其中选出一个包含三个点的子集&#xff0c;这三个点能组成三角形。然而这样的方案太多了&#xff0c;他决定只选择那些可以组成等腰三角形的方案。请帮他计算出一共有多少种选法可以组成等腰三角形&#xff1f…

Convolutional Occupancy Networks【ECCV2020】

论文&#xff1a;https://arxiv.org/pdf/2003.04618 代码&#xff1a;GitHub - autonomousvision/convolutional_occupancy_networks: [ECCV20] Convolutional Occupancy Networks 图 1&#xff1a;卷积占据网络。传统的隐式模型 (a) 由于其全连接网络结构&#xff0c;表现能力…

【30天精通Prometheus:一站式监控实战指南】第4天:node_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…

4月空调行业线上市场销售数据分析

随着生活品质的提升&#xff0c;消费者对家用空调的诉求不仅仅满足于基本制冷制热功能&#xff0c;而是在环保节能、功能升维、舒适送风、智能科技、焕新设计等多维度提出需求。这种多样化的需求推动了空调产品的创新和升级&#xff0c;这不仅提高了空调的市场竞争力&#xff0…

Linux程序开发(六):进程编程和系统日志守护进程

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

“闻起来有股答辩的味道”,答辩到底是什么味?

“闻起来有股答辩的味道”&#xff0c;答辩到底是什么味&#xff1f; 一位名叫“小鸡全家桶”的作者虚构了这样一个学校故事&#xff0c;故事说&#xff0c;由于学生的考试试卷印刷得特别模糊&#xff0c;导致里面的插图根本看不清&#xff0c;学生感到懵逼&#xff0c;监考老…

oracle主机虚拟内存不足导致实例宕机

检查alert日志&#xff0c;发现pga资源分配时报内存不足&#xff1a; 由于pga内存不足&#xff0c;而导致的数据库宕机。 查看操作系统日志&#xff1a; 发现在宕机之前&#xff0c;出现了虚拟内存不足的情况。 检查确认设置的虚拟内存大小为50多G&#xff1a; 按道理不该出现…