我们知道,在MySQL5.6中引入了并行复制模式,当实例上有多个库的时候,可以在备库上对这几个库进行并发操作;这在基于分库的应用场景下,可以显著提升备库的复制效率,但对于我们以分表为主的场景,则效果甚微。
MySQL5.7.2是最新的开发版本release,在该版本中可以看到对复制部分做了非常大的改动,例如半同步复制的after sync, 使用Performance Schema表来监控复制线程,实验室版本的多主复制,以及本文要提到的新的多线程复制模式,MySQL里用一个新的参数来控制:slave_parallel_type,默认值为DATABASE,表示默认行为;另外一个值为LOGICAL_CLOCK,即为新增的模式
1.基本思路
由于MySQL存储引擎层已经保证了同时能够进入事务prepare/commit阶段的事务是没有冲突的(例如Innodb的行锁机制来保证事务的调度),那么可以认为在同时进入Prepare阶段的事务是可以在备库并发执行的,因为他们互相没有冲突;
LOGICAL_CLOCK是一个全局递增的64位长整型数字,主要通过它来判断哪些事务能够并发;
a.分配
在二阶段提交的binlog prepare阶段进行分配
binlog_cache_mngr *const cache_mngr= thd_get_cache_mngr(thd);
cache= cache_mngr->get_binlog_cache_log(all);
if (cache->commit_seq_no == SEQ_UNINIT)
cache->commit_seq_no=
mysql_bin_log.commit_clock.get_timestamp();
}
在之前版本中binlog_prepare函数都是空函数
b.写入
LOGICAL_CLOCK只有记录到binlog中,才能为备库所用,在将每个线程cache的binlog写入时,调用函数write_commit_seq_no,每组事务的第一个事件才记录LOGICAL_CLOCK
具体的存储位置,可以阅读函数Gtid_log_event::Gtid_log_event()
c.递增
MySQL的group commit有三个阶段,FLUSH_STAGE, SYNC_STAGE, 以及COMMIT_STAGE,递增LOGICAL_CLOCK发生在第二阶段结束之后,第三阶段开始之前,这时候SYNC阶段的leader还没有释放LOCK_SYNC。
7300 mysql_bin_log.commit_clock.step();
7301 if (opt_binlog_order_commits)
7302 {
7303 if (change_stage(thd, Stage_manager::COMMIT_STAGE,
7304
这里并不是严格要求所有同时进入Prepare阶段的事务都在备库并发执行,因此一组提交的事务中可能存在不同的seq no
备库根据主库上记录的seq no来决定哪些事务是可以并行的,因此主库上并发线程数越多,复制效果越好,目前代码还处于开发阶段,在试玩时,发现打开gtid时,无法使用该特性,bug链接:http://bugs.mysql.com/bug.php?id=70536 包含具体的代码分析
更具体的可以阅读如下链接:
想知道具体的代码怎么实现的可以看看这个:http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6256
开发人员博客也详细的如何配置step by step:
http://geek.rohitkalhans.com/2013/09/enhancedMTS-configuration.html
以及实现的原理
http://geek.rohitkalhans.com/2013/09/enhancedMTS-deepdive.html