并行复制的概念及实现参考这篇wiki
在并行复制(Multi-Threaded Slave,MTS)模式下
- 一个I/O线程:接收自Master的events/transactions并按顺序写入relay log
- 一个Coordinator线程:将relay log中的events/transactions分发给一组Worker线程
一组Worker线程:执行events/transactions
问题
在MTS模式下,强制性的停止Worker线程可能导致事务流产生空洞(Gaps)
考虑存在如下的场景,有两个Worker线程(红色,蓝色),对于每个event:可能已经执行完成(实心红色/蓝色矩形)
- 可能已经分配到Worker队列还未执行(空心红色/蓝色矩形)
- 可能还未分配到Worker队列(空心橙色矩形)
那么当执行STOP SlAVE时,如果两个Worker线程如果只保证正在执行的事务(Worker1的T4,Worker2的T7)执行完毕后就立即停止,会出现如下场景
未执行的事务T5被夹在已执行完毕的事务流中,产生了空洞(Gaps)
在MySQL 5.6.26之前,STOP SLAVE为了防止Gaps的产生(Gap-Less State),会保证所有Worker已分配到队列中events/transactions都执行完毕,Worker才会停止,会得到如下场景
STOP SLAVE会使Worker等待T8,T9都执行完毕才停止,但会导致STOP SLAVE的执行时间大大延长,尤其是当队列中由大量的events/transactions在排队并且等待执行的情况
优化
在MySQL 5.6.26以及更高版本,当执行STOP SLAVE时,所有Worker试着决议出一个 max_group_index,使得max_group_index是STOP SLAVE后最大的被执行完成的group_index(T7)
- Worker的current_group_index <= max_group_index,执行当前队列中的events/transactions
- Worker的current_group_index > max_group_index,只需要停止线程
- Worker队列为空,只需要停止线程
那么,只需要保证group_inde <= T7的events/transactions得到执行之后,Worker线程即可停止,场景如下: