MySQL备库的并行复制演进
author:陈镇坤27
创建时间:2021年11月30日22:58:34
转载请注明出处
————————————————————————————————
问:简单介绍下MySQL的备库并行复制各版本的演进情况。
答:MySQL5.6之前只支持单线程复制,MySQL5.6时,支持按库的多线程复制,此时MariaDB创新使用了一种独特的并行复制技巧,MySQL5.7借鉴了该技巧,并进一步在事务的prepare进行优化,MySQL5.7.22新增一个类似按行分发复制的设置。
问:MySQL5.6之前的备库单线程复制可能产生什么问题?
答:主备延迟过高。
问:MySQL的多线程复制需要解决什么问题?
答:
1)保证同个事务内的多个更新语句在一个线程内执行——防止事务隔离性被破坏;
2)保证对同个数据更新的多个事务的执行顺序——防止主备数据不一致。
问:在MySQL5.6出现多线程复制之前,备库单线程复制有什么方案可以改进为多线程?
答:(整理专栏作者自己设计的方案)
首先,由一个统筹者(coordinator)读取中转日志(relaylog)后,来给线程进行事务的分发(官方也如此)。
分别是按表分发和按行分发,两者的binlog设置需要是row格式
1)按表分发
事务更新的表在正被大于1个线程处理时,该事务等待,直到<=1
(其实这与一个东西是一个内核思想:操作系统原理——进程管理中的PV操作)
每个线程维护一个hash表,key为表名,value为正执行的事务count。
每次新事务在分发前,都会与所有的线程维护的hash表做比较
若新事物所更新的表只在<=1个线程中执行,则交由该线程执行,否则等待。
(补一个PV图,待定)
事务执行完后,会在对应的worker线程中的所维护的hash表对应表key的事务count-1,若count = 0,则移除该hash键值。
2)按行分发
前面的分发粒度是表,若两个事务更新同一张表,但更新的数据行不同时,其实是可以并行执行的。
按行分发同样要每个线程维护一个hash表,key是“库+表+函数关系的所有候选键组合”(候选键:唯一标识元组)
(待定:对于该专栏的按行策略示例分析解释,本人始终不得要领)
问:刚刚介绍的按表分发和按行分发,各自有什么问题?有什么改善方案?
答:按表分发情况下,对于频繁热点表而言,并行复制能力是失效的。
按行分发情况下,需要耗费更多计算资源(维护hash项,解析binlog),表必须有主键,更新的数据不能有外键(外键情况下,级联更新的行不会记录在binlog上)
此外,两者的主库binlog必须是row格式,方能解析库、表、主键、唯一索引;
如果选择的是按行分发,则设置单个事务的阈值,若超过阈值,则等待,直到所有worker完成后,再单独执行它。(有问题:事务等待过久)
问:介绍下MySQL5.6的并行复制方案。
答:MySQL5.6的并行复制方案基本取决于业务表的压力模型设计,因为该并行复制方案是在库的粒度上进行线程分配的,同样的在每一个worker线程上维护一个hash表,而key则为库名。该方案下,binlog可采用statement格式(可以拿到库名即可)。
缺点:并行能力取决于压力模型,若高频访问集中在一个库中,则达不到并行复制效果。
问:介绍下的MariaDB并行复制方案。
答:正在业界大多都在聚焦在“分析binlog,然后解析到不同的worker上”以提高备库并发复制能力时,MariaDB别出心裁地利用了INnodb事务执行的特点,来实现并发复制。
特点是:在主库能并发执行的事务,在从库也可以并发执行;
一次组提交中,事务不可能发生冲突(修改同一行)。
并发复制实现步骤:每个binlog中组提交中的所有处于commit状态的事务标记一个commit_id,coodinator将同个commit_id的事务分发到一个worker线程。等这些事务全部执行完,再获取下一批。
缺点:在并发过程上,并非“流水线”型,而是批量的单线程型,相比较主库一批事务提交,一批事务正在执行中,这种复制方案一次只能有一批事务处于提交、执行中,影响系统吞吐量,而且,组提交中的大事务会拖慢整体的进度。
问:介绍下的MySQL5.7的并行复制方案。
答:在5.6的库粒度并行复制方案基础上,学习MariaDB的并行复制方案。
有参数slave-parallel-type选择方案。
show variables like 'slave_parallel_type'
set slave_parallel_type = 'DATABASE'
set slave_parallel_type = 'LOGICAL_CLOCK'
不同的是,MySQL5.7的组提交分发进一步进行了优化。
MariaDB是在事务完全提交的基础上进行标记的,而MySQL则是当全部的事务处于prepare阶段,即可进行,因此此时已经经过锁冲突检验了。
并行复制实现步骤:所有处于prepare、commit的事务提交,都是可并行执行的,不发生冲突的。由于事务二阶段提交过程如下:
redo log prepare:write
binlog :write
redo log prepare:fsync
binlog:fsync
redo log commit:write
则通过下列参数设置,拉开binlog上write到fsync之间的时间,让更多的事务处于prepare状态,能一次性提交更多的事务。
show variable like '%binlog_group_commit_sync_delay%'
show variable like '%binlog_group_commit_sync_no_delay_count%'
PS:详见第23篇。
问:介绍下MySQL 5.7.22 的并行复制策略。
答:淘汰了按库分发的粒度,在5.7的组提交的并行复制策略基础上,新增一个选项WRITESET
控制命令
show variables like 'binlog_transaction_dependency_tracking'
set binlog_transaction_dependency_tracking = 'COMMIT_ORDER'
set binlog_transaction_dependency_tracking = 'WRITESET'
set binlog_transaction_dependency_tracking = 'WRITESET_SESSION'
WRITESET方案:在主库执行事务时,会对数据更新的行计算对应的hash值,写入WRITESET集合,hash的key是“库+表+索引名+值”。每行的一个唯一索引对应一个hash值。若事务间的WRITESET没有交集,则说它们没有冲突。
优点:不需要在备库记性大量计算(包含解析binlog的行内容)。对binlog的格式没有要求。
|