概念
MTS
Multi-Threaded Slave,并行复制(代码里常用的缩写)
在Slave重现Relay Log时,由单线程分发event,由多线程并行执行event的特性
Coordinator/Worker
Group
group代表由一系列event组成的事务(在rpl_rli.h的注释中),对其中event做如下分类(在log_event.cc的注释中):
- B-event:起始event,Query_log_event的BEGIN事件
- g-event:包含信息(db_name,table_name等)可以用来计算分发给哪个Worker,Table_map、Query_log_event等
- p-event:一般放在g-event前,如INTVAR_EVENT、RAND_EVENT、USER_VAR_EVENT、BEGIN_LOAD_QUERY_EVENT、APPEND_BLOCK_EVENT
- r-event: 一般放在g-event后,如Delete, Update等“regular” event
- T-event:结束event,XID, COMMIT, ROLLBACK, auto-commit query
约束
并行复制需要满足两个约束来保证Master/Slave上的数据一致性:
[约束1] 一个DB的不同事务分配给一个Worker线程
[约束2] 一个事务涉及到多个DB,则这些DB的操作都需要分配给同一个Worker线程实现
并行复制的总体流程如图
聚焦于函数Log_event::get_slave_worker,函数将event分发到Worker,返回这个Worker的指针
代码中的变量说明
- curr_group_assigned_parts(CGAP):当前Group的映射关系
- Assigned Partition Hash(APH):[TO-DO]
-
逻辑
如果是B-event,p-event
表明是事务的开始,将event加入curr_group_da,表明会在延迟分配,返回Worker为NULL
(curr_group_da:deferred array to hold partition-info-free events)如果是g-event
g-event中包含分发Worker的信息,由map_db_to_worker实现:
[参数] dbname,作为Hash的Key
- last_worker:当前Group上一次分配的Worker(给该event前的g-event分配过的Worker)
- …
[步骤]
- 当前的Group之前已经分配过相同的db_name(在curr_group_assigned_parts,CGAP中查找),直接返回last_worker(约束2)
- CGAP中没查找到,在APH中查找(在Relay Log之前Group中是否有该event的映射关系):
- 返回NULL:使用分配一个Worker,生成映射关系,并插入到APH中
- 返回的Worker没有被Group使用(entry->usage == 0):说明之前没有Group中的event映射过该event,直接将该event映射到last_worker(如果last_worker为NULL,使用get_least_occupied_worker分配一个Worker)
- 返回的Worker == last_worker:直接使用last_worker(约束1)
- 返回的Worker != last_worker:event映射冲突,需要等待引用该映射关系的Group执行结束,再将event映射为last_worker(约束1)
如果是r-event, T-event
返回该Group已分配的Worker(lastassigned_worker)[TO-DO]_表级并行复制
map_db_to_worker函数的声明为:
由以上的分析,函数中会将dbname作为Hash的Key来分配Worker,只需要将dbname修改为dbname(数据库名)+tablename(表名)就可实现表级并行复制