千家信息网

MySQL半同步复制的示例分析

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要介绍MySQL半同步复制的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!代码分析int repl_semi_report_commit(Trans_para
千家信息网最后更新 2026年10月31日MySQL半同步复制的示例分析

这篇文章主要介绍MySQL半同步复制的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!


代码分析

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

  2. {

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

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

  5. {

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

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

  8. }

  9. return 0;

  10. }

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

    • my_off_t trx_wait_binlog_pos)

    • {

    • //自旋锁,下面的代码是线性执行。

    • 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;

    • }

    • //进入信号了,为后面发起信号量的等待动作做准备,每个正在进行提交的事务都对应一个初始化的信号量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;

    • //计算等待ACK的截止时间。按照当前时间加上半同步等待的超时时间,这个时间回在发起信号量等待的时候用的

    • //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表示当前半同步状态为on,否则直接进入l_end。Rpl_semi_sync_master_status

    • //reply_file_name_值的变化,在其他函数中?

    • while (is_on()){

    • if (reply_file_name_inited_){

    • //比较事务所涉及的binlog位置跟reply的位置,如果cmp>0,说明此事务的binlog已经同步

    • //到slave,跳出该循环,进入最后阶段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_){

    • //比较事务所涉及的binlog位置和当前最小需要等待的binlog位置。如果cmp<0,表示调整当前最小需要等待

    • //binlog的位置。rpl_semi_sync_master_wait_pos_backtraverse++,即等待位置需要调整的次数,一般不会

    • //调整

    • 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{

    • //保存第一次最小需要响应的事务位置

    • 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个数是0了,则将半同步关闭,退出循环

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

    • switch_off();

    • break;

    • }

    • //正式进入等待binlog同步的步骤,将rpl_semi_sync_master_wait_sessions+1,表明

    • //有多少要提交的事务线程在等待(这个值是否能够代表实际等待事务的线程数量,值得怀疑,因为该函数

    • //开始位置有lock,没有unlock前,其他线程也进不到这一步,没办法执行++)

    • //然后发起等待信号,进入信号等待后,只有2种情况可以退出等待。1是被其他线程唤醒(binlog dump)

    • //2是等待超时时间。如果是被唤醒则返回值是0,否则是其他值

    • rpl_semi_sync_master_wait_sessions++;

    • entry->n_waiters++;

    • //发起信号等待,然后根据返回结果做相应计数:上面是循环体里面的所有内容,接下来我们看退出循环后的操作。特别提一下,唤醒该线程的dump线程,当dump线程收到相应binlog位置的ack之后,会将其唤醒。

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

    • entry->n_waiters--;

    • rpl_semi_sync_master_wait_sessions--;

    • if (wait_result != 0){

    • //等待超时,关闭半同步

    • rpl_semi_sync_master_wait_timeouts++;

    • switch_off();

    • }else{

    • wait_time = getWaitTime(start_ts);

    • if (wait_time < 0){

    • //表明时钟错误,可能是做了时间调整

    • rpl_semi_sync_master_timefunc_fails++;

    • }else{

    • //将等待事件与该等待计入总数

    • 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、流程总结


      1)在commit函数中,首先需要加一个自旋锁LOCK_binlog_,主要动作都在这个锁内执行。

      2)进入信号,为后面发起信号量的等待动作做准备

      3)计算binlog等待ACK的截止时间。从此时开始+半同步等待的超时时间rpl_semi_sync_master_timeout(默认是10s)

      4)需要在半同步状态下进入下面操作,否则进入l_end。半同步状态的判断是state_,和Rpl_semi_sync_master_status是什么关系?

      5)第一次进来:保存最小需要响应的事务位置wait_file_name_、wait_file_pos_,并将wait_file_name_inited_置成TRUE

      6)最大响应位置reply_file_name_、reply_file_pos_在binlog dump线程修改,和当前binlog(已经flush的?)的位置比较。若当前binlog位置比reply的小,表示次事务的binlog已经到slave了,跳出循环,进入最后阶段l_end

      7)非第一次进来:比较事务涉及的binlog位置和当前最小需要等待的binlog位置。如果比wai_file_name的小,需要将最小需要等待的位置调整到当前位置。rpl_semi_sync_master_wait_pos_backtraverse++,即最小等待位置需要调整的次数。一般不会调整。

      8)第一次进来:需要保存最小需要等待响应的位置为当前位置

      9)接着,需要判断slave个数和半同步是否正常。不正常则退出循环,将半同步关闭

      10)正式进入等待binlog同步的步骤:

      rpl_semi_sync_master_wait_sessions+1:表示有多少提交的事务线程正在等待

      发起信号等待:mysql_cond_timedwait:只有2中情况可以退出等待:1是被其他线程binlog dump唤醒,2是等待超时。

      特别提一下,唤醒该线程的dump线程,当dump线程收到相应binlog位置的ack之后,会将其唤醒。

      等待超时:将半同步关闭

      接收到slave ACK,被binlog dump线程唤醒:修改对应变量

      11)将after_flush步骤插入active_trans的node删掉

      12)直到最后一步才释放锁,因此该函数是整个实例串行的。同时中间有个信号等待的动作。如果数据库并发量很大,而此时主从异常,一旦超时时间设置过大,则可能出现其他用户线程阻塞在lock()函数上,杜塞时间越长,累积的线程越多,容易引发雪崩,所以超时时间设置需谨慎,并非随意设置。

    以上是"MySQL半同步复制的示例分析"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

位置 线程 同步 事务 信号 时间 最小 调整 循环 函数 动作 第一次 信号量 分析 内容 步骤 状态 示例 个数 事务所 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 西安纸贵互联网科技有限公司 科技互联网技术 智网互联网科技 齐家互联网科技 九亚互联网科技 奇士达互联网科技 壕鑫互联网络科技 火传媒上海互联网科技 长亮科技互联网金融 深圳前海聚择互联网科技有限公司 福州新华互联网科技学校 知乎 移动互联网科技股 中国航天科技大学国际工业互联网 互联网在线教育科技创业 中和天地互联网科技有限公司 合肥互联网科技公司公章图片 山东星卡互联网科技有限公司官网 互联网时代科技型公司的机会 安徽零酒互联网科技有限公司 科技互联网企业在行动 互联网科技图片 互联网科技保险 汇久创客互联网科技 润盈互联网科技 银川新华互联网科技学校联系电话 河南住房之家互联网科技 徐州市互联网科技有限公司 扫呗互联网科技有限公司 长沙渺峰互联网科技有限公司 广东猫王互联网科技有限公司电话
0