Loading

MySQL45讲之备库并行复制策略

前言

本文主要介绍 MySQL 备库的并行复制策略。

为什么备库需要并行复制

如果主库有大量更新操作,因为主库可以并发写入,而备库只能单线程执行的话,那么备库的同步延迟会不断累加,即备库越来越追不上主库。所以,后面有了备库的并行复制。

备库的并行复制模型:

并行复制模型

coordinator 职责是分发 binlog 给工作线程,真正执行同步的是 worker。

按表分发策略

每个 worker 工作线程都对应一个表,coordinator 根据 binlog 内容将事务分发到不冲突的 worker 中并行执行,如果发生冲突,则等到不冲突的情况再分发到 worker 中执行。

以“数据库名 + 表名”为键,判断是否冲突:

  1. 如果待分发事务的键和 worker 存在键冲突数等于0,则选择空闲的 worker 执行;

  2. 如果待分发事务的键和 worker 存在键冲突数等于1,则选择冲突的 worker 执行;

  3. 如果待分发事务的键和 worker 存在键冲突数大于1,则等待直到前两个条件符合;

按行分发策略

和按表分发策略同理,不过是以“数据库名 + 表名 + 主键名 + 主键值”或者“数据库名 + 表名 + 唯一键名 + 唯一键值”为键来判断冲突,需要计算更多的键。

为什么还需要判断唯一键是否冲突?
因为并发执行时,执行时序不与原先相同,原先后执行的事务可能现在先执行,有可能会导致不符合唯一性约束,造成数据不一致。

组提交并行策略

MariaDB 提出的并行复制策略

MySQL 组提交的前提是组里面的事务是不冲突的,或者说并行执行不影响数据一致性的。组提交时,在 binlog 中记录 commit_id,那么在备库分发时,将同一个 commit_id 的事务分到不同的 worker 并行执行。

不过,这个方法存在一个缺陷。备库每次执行分发同一个 commit_id 下的事务到 worker 中执行,等都执行完之后,才可以分发下一个 commit_id 对应的事务。这样的话,备库并不是真正地在并行复制,并且,如果一个 commit_id 下的某个事务是大事务,那么将导致下一组执行的时间延后,即存在“短板效应”。

组提交优化策略

MySQL5.7 提出的并行复制策略,在 MariaDB 并行复制策略上进行了优化。

根据 MySQL 两阶段提交,只要处于 prepare 阶段的事务就可以并行执行。所以,下面情况下的事务都可以并行执行:

  1. 同时处于 prepare 的事务

  2. 处于 prepare 和 commit 之间的事务

write_set策略

在主库写入 binlog 之前,计算事务涉及的每一行的 hash 值,写入 binlog,这样在备库分发的时候就不需要解析 binlog 来判断,只需要判断两个事务是否有交集来判断是否可以并行,提交运行效率。

因为不需要解析 binlog 来获取信息,所以该方法下, binlog 采用 statement 和 row 格式都可以。

此外,还有 write_set_session 策略,它在 write_set 策略上加了一个约束,同一个线程先后执行的两个事务,在备库复制时不能并行。

参考

posted @ 2021-10-08 17:13  flowers-bloom  阅读(240)  评论(0编辑  收藏  举报