MySQL5.7.6: 通过序列区间来优化并行复制性能

本文涉及的产品
RDS Agent(兼容OpenClaw),2核4GB
RDS Agent(兼容Hermes Agent),2核4GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介:

我们知道,在MySQL5.7.2中增加了一种新的并行模式:为同时进入COMMIT阶段的事务分配相同的序列号,这些拥有相同序列号的事务在备库是可以并发执行的。

 

具体如何实现参阅我之前的一篇博客: http://mysqllover.com/?p=810

 

在之前的实现中,序列号是在binlog prepare阶段赋值,在engine commit(group commit的第三个阶段)之前递增,因此主库在GROUP COMMIT阶段的并发越高,在备库能够并发执行的事务越多。这个序列号被写入binlog中,备库根据序列号决定哪些事务可以并发执行。

 

然而我们考虑如下序列(Copy from worklog…)

 

    Trx1 ------------P----------C-------------------------------->
                                |
    Trx2 ----------------P------+---C---------------------------->
                                |   |
    Trx3 -------------------P---+---+-----C---------------------->
                                |   |     |
    Trx4 -----------------------+-P-+-----+----C----------------->
                                |   |     |    |
    Trx5 -----------------------+---+-P---+----+---C------------->
                                |   |     |    |   |
    Trx6 -----------------------+---+---P-+----+---+---C---------->
                                |   |     |    |   |   |
    Trx7 -----------------------+---+-----+----+---+-P-+--C------->
                                |   |     |    |   |   |  |

 

在之前的逻辑中,trx5 和 trx6是可以并发执行的,因为他们拥有相同的序列号;Trx4无法和Trx5并行,因为他们的序列号不同。同样的trx6和trx7也无法并行。当发现一个无法并发的事务时,就需要等待前面的事务执行完成才能继续下去,这会影响到备库的TPS。

 

但是理论上trx4应该可以和trx5和trx6并行,因为trx4先于trx5和trx6 prepare,如果trx5 和trx6能进入Prepare阶段,证明其和trx4是没有冲突的。

 

 

解决方案:

 

0.增加两个全局变量:

   /* Committed transactions timestamp */
Logical_clock max_committed_transaction;
/* "Prepared" transactions timestamp */
Logical_clock transaction_counter;

每个事务对应两个counter:last_committed 及 sequence_number

 

1.每次rotate或打开新的binlog时
MYSQL_BIN_LOG::open_binlog:
max_committed_transaction.update_offset(transaction_counter.get_timestamp());
transaction_counter.update_offset(transaction_counter.get_timestamp());
—>更新max_committed_transaction和transaction_counter的offset为当前的state值(或者说,为上个Binlog文件最大的transaction counter值)

 

 

2.每执行一条DML语句完成时,更新当前会话的 last_committed= mysql_bin_log.max_committed_transaction
参考函数: binlog_prepare (参数all为false)

 

3. 事务提交时,写入binlog之前
binlog_cache_data::flush:
trn_ctx->sequence_number= mysql_bin_log.transaction_counter.step();
其中transaction_counter递增1

 

4.写入binlog
将sequence_number 和 last_committed写入binlog
MYSQL_BIN_LOG::write_gtid
记录binlog文件的seq number 和last committed会减去max_committed_transaction.get_offset(),也就是说,每个Binlog文件的序列号总是从(last_committed, sequence_number)=(0,1)开始

 

5.引擎层提交每个事务前更新max_committed_transaction
如果当前事务的sequence_number大于max_committed_transaction,则更新max_committed_transaction的值
MYSQL_BIN_LOG::process_commit_stage_queue –> MYSQL_BIN_LOG::update_max_committed

 

 

6.备库并发检查
函数:Mts_submode_logical_clock::schedule_next_event

 

假设初始状态下transaction_counter=1, max_committed_transaction=1, 以上述流程为例,每个事务的<last_committed,  sequence_number>序列为:
Trx1 prepare: last_commited = max_committed_transaction = 1;
Trx2 prepare: last_commited = max_committed_transaction = 1;
Trx3 prepare: last_commited = max_committed_transaction = 1;
Trx1 commit: sequence_number=++transaction_counter = 2, (transaction_counter=2, max_committed_transaction=2), write(1,2)
Trx4 prepare: last_commited =max_committed_transaction = 2;
Trx2 commit: sequence_number=++transaction_counter= 3,  (transaction_counter=3, max_committed_transaction=3), write(1,3)
Trx5 prepare: last_commited = max_committed_transaction = 3;
Trx6 prepare: last_commited = max_committed_transaction = 3;
Trx3 commit:  sequence_number=++transaction_counter= 4, (transaction_counter=4, max_committed_transaction=4), write(1,4)
Trx4 commit:  sequence_number=++transaction_counter= 5, (transaction_counter=5, max_committed_transaction=5), write(2, 5)
Trx5 commit:  sequence_number=++transaction_counter= 6, (transaction_counter=6, max_committed_transaction=6), write(3, 6)
Trx7 prepare: last_commited = max_committed_transaction = 6;
Trx6 commit:  sequence_number=++transaction_counter= 7, (transaction_counter=7, max_committed_transaction=7), write(3, 7)
Trx7 commit:  sequence_number=++transaction_counter= 8, (transaction_counter=8, max_committed_transaction=8), write(6, 8)

 

并发规则:
因此上述序列中可以并发的序列为:
trx1 1…..2
trx2 1………….3
trx3 1…………………….4
trx4        2………………………….5
trx5               3………………………………..6
trx6               3………………………………………………7
trx7                                                       6……………………..8

 

 

备库并行规则:当分发一个事务时,其last_committed 序列号比当前正在执行的事务的最小sequence_number要小时,则允许执行。
因此,
a)trx1执行,last_commit<2的可并发,trx2, trx3可继续分发执行
b)trx1执行完成后,last_commit < 3的可以执行, trx4可分发
c)trx2执行完成后,last_commit < 4的可以执行, trx5, trx6可分发
d)trx3、trx4、trx5完成后,last_commit < 7的可以执行,trx7可分发

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
10月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
587 158
|
10月前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(中)
使用MYSQL Report分析数据库性能
626 156
|
10月前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(上)
最终建议:当前系统是完美的读密集型负载模型,优化重点应放在减少行读取量和提高数据定位效率。通过索引优化、分区策略和内存缓存,预期可降低30%的CPU负载,同时保持100%的缓冲池命中率。建议每百万次查询后刷新统计信息以持续优化
738 161
|
SQL 缓存 关系型数据库
MySQL 慢查询是怎样优化的
本文深入解析了MySQL查询速度变慢的原因及优化策略,涵盖查询缓存、执行流程、SQL优化、执行计划分析(如EXPLAIN)、查询状态查看等内容,帮助开发者快速定位并解决慢查询问题。
471 0
|
11月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
396 6
|
12月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
306 2
|
关系型数据库 MySQL 分布式数据库
Super MySQL|揭秘PolarDB全异步执行架构,高并发场景性能利器
阿里云瑶池旗下的云原生数据库PolarDB MySQL版设计了基于协程的全异步执行架构,实现鉴权、事务提交、锁等待等核心逻辑的异步化执行,这是业界首个真正意义上实现全异步执行架构的MySQL数据库产品,显著提升了PolarDB MySQL的高并发处理能力,其中通用写入性能提升超过70%,长尾延迟降低60%以上。
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
11月前
|
缓存 关系型数据库 MySQL
MySQL数据库性能调优:实用技术与策略
通过秉持以上的策略实施具体的优化措施,可以确保MySQL数据库的高效稳定运行。务必结合具体情况,动态调整优化策略,才能充分发挥数据库的性能潜力。
544 0
|
12月前
|
存储 SQL 关系型数据库
MySQL 动态分区管理:自动化与优化实践
本文介绍了如何利用 MySQL 的存储过程与事件调度器实现动态分区管理,自动化应对数据增长,提升查询性能与数据管理效率,并详细解析了分区创建、冲突避免及实际应用中的关键注意事项。
486 0

推荐镜像

更多