相關檔案:
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時被中斷。
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且保證資料不丢失
下回分解……….