- 求職 : Linux運(yùn)維
- 論壇徽章:
- 203
|
備庫(kù)如何發(fā)起DUMP請(qǐng)求
引入GTID,最大的好處當(dāng)然是我們可以隨心所欲的切換主備拓?fù)浣Y(jié)構(gòu)了。在一個(gè)正常運(yùn)行的復(fù)制結(jié)構(gòu)中,我們可以在備庫(kù)簡(jiǎn)單的執(zhí)行如下SQL:
CHANGE MASTER TO MASTER_USER=’$USERNAME’, MASTER_HOST=’ ‘, MASTER_PORT=’ ‘, MASTER_AUTO_POSITION=1;
打開(kāi)GTID后,我們就無(wú)需指定binlog文件或者位置,MySQL會(huì)自動(dòng)為我們做這些事情。這里的關(guān)鍵就是MASTER_AUTO_POSITION。IO線程連接主庫(kù),可以大概分為以下幾步:
1.IO線程在和主庫(kù)建立TCP鏈接后,會(huì)去獲取主庫(kù)的uuid(get_master_uuid),然后在主庫(kù)上設(shè)置一個(gè)用戶變量@slave_uuid(io_thread_init_commands)
2.之后,在主庫(kù)上注冊(cè)SLAVE(register_slave_on_master)
在主庫(kù)上調(diào)用register_slave來(lái)注冊(cè)備庫(kù),將備庫(kù)的host,user,password,port,server_id等信息記錄到slave_list哈希中。
3.調(diào)用request_dump,開(kāi)始向主庫(kù)請(qǐng)求數(shù)據(jù),這里分兩種情況:
MASTER_AUTO_POSITION=0時(shí),向主庫(kù)發(fā)送命令的類型為COM_BINLOG_DUMP,這是傳統(tǒng)的請(qǐng)求BINLOG的模式
MASTER_AUTO_POSITION=1時(shí),命令類型為COM_BINLOG_DUMP_GTID,這是新的方式。
這里我們只討論第二種。第二種情況下,會(huì)先去讀取備庫(kù)已經(jīng)執(zhí)行的gtid集合
quoted code in rpl_slave.cc :
2974 if (command == COM_BINLOG_DUMP_GTID)
2975 {
2976 // get set of GTIDs
2977 Sid_map sid_map(NULL/*no lock needed*/);
2978 Gtid_set gtid_executed(&sid_map);
2979 global_sid_lock->wrlock();
2980 gtid_state->dbug_print();
2981 if (gtid_executed.add_gtid_set(mi->rli->get_gtid_set()) != RETURN_STATUS_OK ||
2982 gtid_executed.add_gtid_set(gtid_state->get_logged_gtids()) !=
2983 RETURN_STATUS_OK)
構(gòu)建完成發(fā)送包后,發(fā)送給主庫(kù)。
在主庫(kù)上接受到命令后,調(diào)用入口函數(shù)com_binlog_dump_gtid,流程如下:
1.slave_gtid_executed.add_gtid_encoding(packet_position, data_size) ;讀取備庫(kù)傳來(lái)的GTID SET
2.讀取備庫(kù)的uuid(get_slave_uuid),被根據(jù)uuid來(lái)kill僵尸線程(kill_zombie_dump_threads)
這也是之前SLAVE IO線程執(zhí)行SET @SLAVE_UUID的用處。
3.進(jìn)入mysql_binlog_send函數(shù):
|–>調(diào)用MYSQL_BIN_LOG::find_first_log_not_in_gtid_set,從最后一個(gè)Binlog開(kāi)始掃描,獲取文件頭部的PREVIOUS_GTIDS_LOG_EVENT,如果它是slave_gtid_executed的子集,保存當(dāng)前binlog文件名,否則繼續(xù)向前掃描。
這一步的目的就是為了找出備庫(kù)執(zhí)行到的最后一個(gè)Binlog文件。
|–>從這個(gè)文件頭部開(kāi)始掃描,遇到GTID_EVENT時(shí),會(huì)去判斷該GTID是否包含在slave_gtid_executed中:
Gtid_log_event gtid_ev(packet->ptr() + ev_offset,
packet->length() – checksum_size,
p_fdle);
skip_group= slave_gtid_executed->contains_gtid(gtid_ev.get_sidno(sid_map),
gtid_ev.get_gno());
主庫(kù)通過(guò)GTID決定是否可以忽略事務(wù),從而決定執(zhí)行開(kāi)始的位置
注意,在使用MASTER_LOG_POSITION后,就不要指定binlog的位置,否則會(huì)報(bào)錯(cuò)。 |
|