天天看点

MySQL支持多线程复制

我们知道从5.6开始,mysql支持多线程复制,到5.7版本又引入了基于group commit的并发事务分发机制。这意味着没有冲突的事务可以在备库并发执行。很显然,备库的事务提交顺序和主库是不能保证一致的。

这可能带来一些问题,尤其是事务之间有一定的业务关联时,提供读访问时可能会带来业务上的不一致问题。因此在mysql 5.7.6版本,引入了一个新的特性,来保证主库和备库的commit顺序是一致的。

对应的changelog:

replication: multi-threaded slaves can use the new slave_preserve_commit_order variable to ensure that the order which transactions were committed on the master is preserved on the slave. this prevents the slave from entering a state that the master was not in and is well suited to using multi-threaded slaves for replication read scale-out.

主要修改思路:

增加了新类commit_order_manager,来维护commit的worker队列顺序。当start slave时,发现选项被打开,使用多线程复制,并且备库的log_slave_update和binlog均打开时,就初始化一个类对象(handle_slave_sql)

当使用基于logic clock的方式来分发事务时,这些被分发的事务拥有相同的标记(在主库上同时被提交,可以确保没有事务冲突),因此可以被备库的worker线程并发执行。

在分配事务给一个worker线程时,worker入队列(mts_submode_logical_clock::get_least_occupied_worker),调用函数commit_order_manager::register_trx, 线程状态设置为ocs_wait

在事务commit,进入group commit的flush stage之前,如果当前worker之前还有事务没有进入flush stage,则等待(commit_order_manager::wait_for_its_turn);直到该worker成为队列头,状态设置为ocs_signal。

进入flush stage后,当前worker会通知它的后一个worker可以进入flush stage了,并将自己从队列中移除(mngr->unregister_trx(worker))。worker状态修改为ocs_finish。

由于flush stage主要用于将binlog 从cache刷入文件,因此只要在该阶段保证有序即可。

另外为了保证有序性,一旦前面的事务执行失败,排在后面的worker都需要进行回滚。

继续阅读