相关文件:
rpl_slave.cc rpl_slave.h rpl_rli_pdb.cc rpl_rli_pdb.h
1.启动slave.
init_slave
|—>start_slave_threads
|—>handle_slave_io(IO thread) 启动IO线程
|—>handle_slave_sql(SQL thread) 启动SQL线程(作为协调者)
|—>slave_start_workers(Worker thread)
|—->handle_slave_worker 启动worker线程
2.
handle_slave_worker
|—>while (!error)
|—>{
|—> error= slave_worker_exec_job(w, rli);
|—>job_item= pop_jobs_item()
|—>读取worker->jobs队列的头部(head_queue),没有的话则等待(worker->jobs_cond)
|—>error= ev->do_apply_event_worker(worker);
|—>}
|—>while(de_queue(&w->jobs, job_item)) 清理队列中的事件
|—>必要的清理后退出
worker线程在pop_jobs_item的检查点:
while (!job_item->data && !thd->killed &&
worker->running_status == Slave_worker::RUNNING)
因此当线程被kill或者 worker->running_status被置为NOT_RUNNING时被中断。
因此当线程被kill或者 worker->running_status被置为NOT_RUNNING时被中断。
3.
handle_slave_sql
|—> slave_start_workers 开启worker线程
|—> rli->init_relay_log_pos 初始化relay log pos
|—>while (!sql_slave_killed(thd,rli)){
|—>exec_relay_log_event(thd,rli)
|—>ev = next_event(rli) 读取事件
|—>exec_res= apply_event_and_update_pos(ptr_ev, thd, rli);
|—>ev->apply_event
调用Log_event::apply_event,在以下情况下,SQL线程会直接执行事件
1.处于recovery状态
2.worker线程数为0
3.执行某些特定事件需要串行化时,由SQL线程来执行,会先调用
当需要串行化时,会调用wait_for_workers_to_finish等待worker线程完成
以上情况直接调用do_apply_event(),否则就将事件指定给某个worker线程
(Log_event::get_slave_worker)
|—>更新position,这里要考虑到crash-safe
|—->slave被kill或出现错误,slave_stop_workers(rli, &mts_inited)
对每个sql线程,先设置w->running_status= Slave_worker::KILLED再等待其变成Slave_worker::NOT_RUNNING
每个Worker线程有一个slave_worker结构体,其作用类似于之前的relay_log_info
以上简单的描述了并行复制部分的代码架构,写的很简单,可能会有些小的错误,后续在深入了解时,会进行校正。接着关注的内容是:如何安全的进行safe-recovery且保证数据不丢失
下回分解……….