真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

MySQL半同步復(fù)制的示例分析

這篇文章主要介紹MySQL半同步復(fù)制的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)公司是專業(yè)的金塔網(wǎng)站建設(shè)公司,金塔接單;提供成都做網(wǎng)站、成都網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行金塔網(wǎng)站開發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!


代碼分析

  1. int repl_semi_report_commit(Trans_param *param)//gdb下param?  

  2. {  

  3.   

  4.   bool is_real_trans= param->flags & TRANS_IS_REAL_TRANS;  

  5.   

  6.   if (is_real_trans && param->log_pos)  

  7.   {  

  8.     const char *binlog_name= param->log_file;  

  9.     return repl_semisync.commitTrx(binlog_name, param->log_pos);  

  10.   }  

  11.   return 0;  

  12. }

    • int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,  

    •                   my_off_t trx_wait_binlog_pos)  

    • {  

    •     //自旋鎖,下面的代碼是線性執(zhí)行。  

    •     mysql_mutex_lock(&LOCK_binlog_);  

    •     if (active_tranxs_ != NULL && trx_wait_binlog_name){  

    •         entry=active_tranxs_->find_active_tranx_node(trx_wait_binlog_name,  

    •                                              trx_wait_binlog_pos);  

    •         if (entry)  

    •             thd_cond= &entry->cond;  

    •     }  

    •     //進(jìn)入信號(hào)了,為后面發(fā)起信號(hào)量的等待動(dòng)作做準(zhǔn)備,每個(gè)正在進(jìn)行提交的事務(wù)都對(duì)應(yīng)一個(gè)初始化的信號(hào)量thd_cond  

    •     THD_ENTER_COND(NULL, thd_cond, &LOCK_binlog_,  

    •                  & stage_waiting_for_semi_sync_ack_from_slave,  

    •                  & old_stage);  

    •     if (getMasterEnabled() && trx_wait_binlog_name){  

    •         set_timespec(start_ts, 0);//  

    •         if (!getMasterEnabled() || !is_on())  

    •             goto l_end;  

    •         //計(jì)算等待ACK的截止時(shí)間。按照當(dāng)前時(shí)間加上半同步等待的超時(shí)時(shí)間,這個(gè)時(shí)間回在發(fā)起信號(hào)量等待的時(shí)候用的  

    •         //rpl_semi_sync_master_timeout  

    •         abstime.tv_sec = start_ts.tv_sec + wait_timeout_ / TIME_THOUSAND;  

    •         abstime.tv_nsec = start_ts.tv_nsec +(wait_timeout_ % TIME_THOUSAND) * TIME_MILLION;  

    •         if (abstime.tv_nsec >= TIME_BILLION){  

    •             abstime.tv_sec++;  

    •             abstime.tv_nsec -= TIME_BILLION;  

    •         }  

    •         //state_是TRUE表示當(dāng)前半同步狀態(tài)為on,否則直接進(jìn)入l_end。Rpl_semi_sync_master_status  

    •         //reply_file_name_值的變化,在其他函數(shù)中?  

    •         while (is_on()){  

    •             if (reply_file_name_inited_){  

    •                 //比較事務(wù)所涉及的binlog位置跟reply的位置,如果cmp>0,說明此事務(wù)的binlog已經(jīng)同步  

    •                 //到slave,跳出該循環(huán),進(jìn)入最后階段l_end  

    •                 int cmp = ActiveTranx::compare(reply_file_name_, reply_file_pos_,  

    •                                        trx_wait_binlog_name, trx_wait_binlog_pos);  

    •                 if (cmp >= 0){  

    •                     break;  

    •                 }  

    •             }  

    •             if (wait_file_name_inited_){  

    •                 //比較事務(wù)所涉及的binlog位置和當(dāng)前最小需要等待的binlog位置。如果cmp<0,表示調(diào)整當(dāng)前最小需要等待  

    •                 //binlog的位置。rpl_semi_sync_master_wait_pos_backtraverse++,即等待位置需要調(diào)整的次數(shù),一般不會(huì)  

    •                 //調(diào)整  

    •                 int cmp = ActiveTranx::compare(trx_wait_binlog_name, trx_wait_binlog_pos,  

    •                                        wait_file_name_, wait_file_pos_);  

    •                  if (cmp <= 0){  

    •                     strncpy(wait_file_name_, trx_wait_binlog_name, sizeof(wait_file_name_) - 1);  

    •                     wait_file_name_[sizeof(wait_file_name_) - 1]= '\0';  

    •                     wait_file_pos_ = trx_wait_binlog_pos;  

    •                     rpl_semi_sync_master_wait_pos_backtraverse++;  

    •                  }  

    •                    

    •             }else{  

    •                 //保存第一次最小需要響應(yīng)的事務(wù)位置  

    •                 strncpy(wait_file_name_, trx_wait_binlog_name, sizeof(wait_file_name_) - 1);  

    •                 wait_file_name_[sizeof(wait_file_name_) - 1]= '\0';  

    •                 wait_file_pos_ = trx_wait_binlog_pos;  

    •                 wait_file_name_inited_ = true;  

    •             }  

    •             //如果salve個(gè)數(shù)是0了,則將半同步關(guān)閉,退出循環(huán)  

    •             if (abort_loop && rpl_semi_sync_master_clients == 0 && is_on()){  

    •                 switch_off();  

    •                 break;  

    •             }  

    •             //正式進(jìn)入等待binlog同步的步驟,將rpl_semi_sync_master_wait_sessions+1,表明  

    •             //有多少要提交的事務(wù)線程在等待(這個(gè)值是否能夠代表實(shí)際等待事務(wù)的線程數(shù)量,值得懷疑,因?yàn)樵摵瘮?shù)  

    •             //開始位置有l(wèi)ock,沒有unlock前,其他線程也進(jìn)不到這一步,沒辦法執(zhí)行++)  

    •             //然后發(fā)起等待信號(hào),進(jìn)入信號(hào)等待后,只有2種情況可以退出等待。1是被其他線程喚醒(binlog dump)  

    •             //2是等待超時(shí)時(shí)間。如果是被喚醒則返回值是0,否則是其他值  

    •             rpl_semi_sync_master_wait_sessions++;  

    •             entry->n_waiters++;  

    •             //發(fā)起信號(hào)等待,然后根據(jù)返回結(jié)果做相應(yīng)計(jì)數(shù):上面是循環(huán)體里面的所有內(nèi)容,接下來(lái)我們看退出循環(huán)后的操作。特別提一下,喚醒該線程的dump線程,當(dāng)dump線程收到相應(yīng)binlog位置的ack之后,會(huì)將其喚醒。  

    •             wait_result= mysql_cond_timedwait(&entry->cond, &LOCK_binlog_, &abstime);  

    •             entry->n_waiters--;  

    •             rpl_semi_sync_master_wait_sessions--;  

    •             if (wait_result != 0){  

    •                 //等待超時(shí),關(guān)閉半同步  

    •                 rpl_semi_sync_master_wait_timeouts++;  

    •                 switch_off();  

    •             }else{  

    •                  wait_time = getWaitTime(start_ts);  

    •                  if (wait_time < 0){  

    •                      //表明時(shí)鐘錯(cuò)誤,可能是做了時(shí)間調(diào)整  

    •                     rpl_semi_sync_master_timefunc_fails++;  

    •                  }else{  

    •                      //將等待事件與該等待計(jì)入總數(shù)  

    •                     rpl_semi_sync_master_trx_wait_num++;  

    •                     rpl_semi_sync_master_trx_wait_time += wait_time;  

    •                  }  

    •             }  

    •         }//end while  

    • l_end:  

    •         /* Update the status counter. */  

    •         if (is_on())  

    •             rpl_semi_sync_master_yes_transactions++;  

    •         else  

    •             rpl_semi_sync_master_no_transactions++;  

    •               

    •     }  

    •     /* Last waiter removes the TranxNode */  

    •     if (trx_wait_binlog_name && active_tranxs_  

    •         && entry && entry->n_waiters == 0)  

    •         active_tranxs_->clear_active_tranx_nodes(trx_wait_binlog_name,  

    •                                              trx_wait_binlog_pos);  

    •     THD_EXIT_COND(NULL, & old_stage);  

    •   

    • }  

    • 3、流程總結(jié)

      1)在commit函數(shù)中,首先需要加一個(gè)自旋鎖LOCK_binlog_,主要?jiǎng)幼鞫荚谶@個(gè)鎖內(nèi)執(zhí)行。

      2)進(jìn)入信號(hào),為后面發(fā)起信號(hào)量的等待動(dòng)作做準(zhǔn)備

      3)計(jì)算binlog等待ACK的截止時(shí)間。從此時(shí)開始+半同步等待的超時(shí)時(shí)間rpl_semi_sync_master_timeout(默認(rèn)是10s)

      4)需要在半同步狀態(tài)下進(jìn)入下面操作,否則進(jìn)入l_end。半同步狀態(tài)的判斷是state_,和Rpl_semi_sync_master_status是什么關(guān)系?

      5)第一次進(jìn)來(lái):保存最小需要響應(yīng)的事務(wù)位置wait_file_name_、wait_file_pos_,并將wait_file_name_inited_置成TRUE

      6)最大響應(yīng)位置reply_file_name_、reply_file_pos_在binlog dump線程修改,和當(dāng)前binlog(已經(jīng)flush的?)的位置比較。若當(dāng)前binlog位置比reply的小,表示次事務(wù)的binlog已經(jīng)到slave了,跳出循環(huán),進(jìn)入最后階段l_end

      7)非第一次進(jìn)來(lái):比較事務(wù)涉及的binlog位置和當(dāng)前最小需要等待的binlog位置。如果比wai_file_name的小,需要將最小需要等待的位置調(diào)整到當(dāng)前位置。rpl_semi_sync_master_wait_pos_backtraverse++,即最小等待位置需要調(diào)整的次數(shù)。一般不會(huì)調(diào)整。

      8)第一次進(jìn)來(lái):需要保存最小需要等待響應(yīng)的位置為當(dāng)前位置

      9)接著,需要判斷slave個(gè)數(shù)和半同步是否正常。不正常則退出循環(huán),將半同步關(guān)閉

      10)正式進(jìn)入等待binlog同步的步驟:

              rpl_semi_sync_master_wait_sessions+1:表示有多少提交的事務(wù)線程正在等待

              發(fā)起信號(hào)等待:mysql_cond_timedwait:只有2中情況可以退出等待:1是被其他線程binlog dump喚醒,2是等待超時(shí)。

             特別提一下,喚醒該線程的dump線程,當(dāng)dump線程收到相應(yīng)binlog位置的ack之后,會(huì)將其喚醒。

             等待超時(shí):將半同步關(guān)閉

             接收到slave ACK,被binlog dump線程喚醒:修改對(duì)應(yīng)變量

      11)將after_flush步驟插入active_trans的node刪掉

      12)直到最后一步才釋放鎖,因此該函數(shù)是整個(gè)實(shí)例串行的。同時(shí)中間有個(gè)信號(hào)等待的動(dòng)作。如果數(shù)據(jù)庫(kù)并發(fā)量很大,而此時(shí)主從異常,一旦超時(shí)時(shí)間設(shè)置過大,則可能出現(xiàn)其他用戶線程阻塞在lock()函數(shù)上,杜塞時(shí)間越長(zhǎng),累積的線程越多,容易引發(fā)雪崩,所以超時(shí)時(shí)間設(shè)置需謹(jǐn)慎,并非隨意設(shè)置。

    以上是“MySQL半同步復(fù)制的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


    網(wǎng)站名稱:MySQL半同步復(fù)制的示例分析
    鏈接地址:http://weahome.cn/article/pdieij.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部