MySQL备库并行复制策略
备库并行复制策略
按表分发
按表分发事务的基本思路是,如果两个事务更新不同的表,它们就可以并行。因为数据是存储在表里的,所以按表分发,可以保证两个worker不会更新同一行。
每个事务在分发的时候,跟所有worker的冲突关系包括以下三种情况:
- 如果跟所有worker都不冲突,coordinator线程就会把这个事务分配给最空闲的woker;
- 如果跟多于一个worker冲突,coordinator线程就进入等待状态,直到和这个事务存在冲突关系的worker只剩下1个;
- 如果只跟一个worker冲突,coordinator线程就会把这个事务分配给这个存在冲突关系的worker。
按行分发
要解决热点表的并行复制问题,就需要一个按行并行复制的方案。按行复制的核心思路是:如果两个事务没有更新相同的行,它们在备库上可以并行执行。显然,这个模式要求binlog格式必须是row。
按行复制和按表复制的数据结构差不多,也是为每个worker,分配一个hash表。只是要实现按行分发,这时候的key,就必须是“库名+表名+唯一键的值”。(如果存在唯一索引也需要加上唯一索引)
按行分发的策略有两个问题:
- 耗费内存。比如一个语句要删除100万行数据,这时候hash表就要记录100万个项。
- 耗费CPU。解析binlog,然后计算hash值,对于大事务,这个成本还是很高的。
MariaDB的并行复制策略
MariaDB是这么做的:
- 在一组里面一起提交的事务,有一个相同的commit_id,下一组就是commit_id+1;
- commit_id直接写到binlog里面;
- 传到备库应用的时候,相同commit_id的事务分发到多个worker执行;
- 这一组全部执行完成后,coordinator再去取下一批。
MySQL 5.6版本的并行复制策略用于的是:按库并行。
MySQL 5.6版本的并行复制策略用的是:类似于MariaDB的策略。
MySQL 5.7.22的并行复制策略用的是:按行并行。
不过,MySQL官方的这个实现还是有很大的优势:
- writeset是在主库生成后直接写入到binlog里面的,这样在备库执行的时候,不需要解析binlog内容(event里的行数据),节省了很多计算量;
- 不需要把整个事务的binlog都扫一遍才能决定分发到哪个worker,更省内存;
- 由于备库的分发策略不依赖于binlog内容,所以binlog是statement格式也是可以的。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 goMars的学习随记!
评论