26 | 备库为什么会延迟好几个小时

前面提到的场景里,不论是偶发的查询压力,还是备份,对备库延迟的影响一般都是分钟级的,而且在备库恢复正常以后都能够追上来。

但是,如果备库的执行日志的速度持续低于主库生成日志的速度,那这个延迟就有可能成了小时级别。而且对于一个压力持续比较高的主库来说,备库很可能永远都追不上主库的节奏。

备库并行复制能力。

主备流程图:

备库日志执行比主库生成日志慢,意思就是图中上面的黑色箭头比下面黑色箭头粗。

如果备库sql_thread用单线程的话,就可能会导致备库应用日志不够快,造成主备延迟。

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

多线程复制,就是要把图中只有一个线程的sql_thread,折成多个线程,符合下面的模型:

work线程的个数,由参数slave_parallel_workers决定的。一般这个值设置为8~16之间最好(32核物理机的情况),备库还有可能要提供读查询,不能把CPU都吃光了。

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

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

MySQL 5.5版本的并行复制策略(非官方版本)

按表分发策略

思路:如果两个事务更新不同的表,它们就可以并行。因为数据是存储在表里的,所以按表分发,就可以保证两个worker不会更新同一行。当然,如果有跨表的事务,还是要把两张表放在一起考虑。

按行分发策略

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

相比按表分发策略,按行并行策略在决定线程分发的时候,需要消耗更多的计算机资源。

MySQL 5.6版本的并行复制策略(官方)

官方MySQL 5.6版本,支持了并行复制,只是支持粒度是按库并行。

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

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

  1. 构造hash值的时候很快,只需要库名;而且一个实例上DB数也不会很多,不会出现需要构造100万个项的情况。
  2. 不要求binlog的格式。因为statement格式的binlog也可以很容易拿到库名。

但是,如果主库上的表都放在同一个DB里面,这个策略就没有效果了;或者如果不同DB的热点不同,也起不到并行的效果。

MariaDB的并行复制策略

利用redo log组提交特性:

  1. 能够在同一组里提交的事务,一定不会修改同一行;
  2. 主库上可以并行执行的事务,备库上也一定是可以并行执行的。

实现上,MariaDB是这么做的:

  1. 在一组里面一起提交的事务,有一个相同的commit_id,下一组就是commit_id+1;
  2. commit_id直接写到binlog里面;
  3. 传到备库应用的时候,相同commit_id的事务分发到多个worker执行;
  4. 这一组全部执行完后,coordinator再去取下一批。

存在的问题:并没实现“真正的模拟主库并发度”这个目标。在主库上,一组事务在commit的时候,下一组事务是同时处于“执行中”状态的。但是这个策略,在备库上执行的时候,要等第一组事务执行完后,第二组事务才能开始执行,这样系统的吞吐量就不够。

统一被大事务拖后腿。

MySQL 5.7的并行复制策略

类似MariaDB的功能,有参数slave-parallel-type来控制并行复制策略:

  1. 配置为DATABASE,表示使用MySQL 5.6版本的按库并行策略;
  2. 配置为LOGICAL_CLOCK,表示的就是类似MariaDB的策略。不过,MySQL 5.7版本这个策略,针对并行度做了优化。

优化思路:

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

MySQL 5.7.22的并行复制策略

基于WRITESET的并行复制

新增了一个参数binlog-transaction-dependency-tracking,用来控制是否启用这个新策略:

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

 

上一篇:25 | MySQL是怎么保证高可用的?

下一篇:27 | 主库出问题了,从库怎么办?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值