分享更有价值
被信任是一种快乐

MySQL半同步复制的示例分析

文章页正文上

这篇文章主要介绍MySQL半同步复制的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
代码分析
intrepl_semi_report_commit(Trans_param*param)//gdb下param?{boolis_real_trans=param->flags&TRANS_IS_REAL_TRANS;if(is_real_trans&&param->log_pos){constchar*binlog_name=param->log_file;returnrepl_semisync.commitTrx(binlog_name,param->log_pos);}return0;}intReplSemiSyncMaster::commitTrx(constchar*trx_wait_binlog_name,my_off_ttrx_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_condTHD_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())gotol_end;//计算等待ACK的截止时间。按照当前时间加上半同步等待的超时时间,这个时间回在发起信号量等待的时候用的//rpl_semi_sync_master_timeoutabstime.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_endintcmp=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//binlog的位置。rpl_semi_sync_master_wait_pos_backtraverse++,即等待位置需要调整的次数,一般不会//调整intcmp=ActiveTranx::compare(trx_wait_binlog_name,trx_wait_binlog_pos,wait_file_name_,wait_file_pos_);if(cmpstrncpy(wait_file_name_,trx_wait_binlog_name,sizeof(wait_file_name_)-1);wait_file_name_[sizeof(wait_file_name_)-1]=’’;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]=’’;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是被其他线程唤醒(binlogdump)//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//表明时钟错误,可能是做了时间调整rpl_semi_sync_master_timefunc_fails++;}else{//将等待事件与该等待计入总数rpl_semi_sync_master_trx_wait_num++;rpl_semi_sync_master_trx_wait_time+=wait_time;}}}//endwhilel_end:/*Updatethestatuscounter.*/if(is_on())rpl_semi_sync_master_yes_transactions++;elserpl_semi_sync_master_no_transactions++;}/*LastwaiterremovestheTranxNode*/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);}
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_置成TRUE6)最大响应位置reply_file_name_、reply_file_pos_在binlog dump线程修改,和当前binlog(已经flush的?)的位置比较。若当前binlog位置比reply的小,表示次事务的binlog已经到slave了,跳出循环,进入最后阶段l_end7)非第一次进来:比较事务涉及的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半同步复制的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注云技术行业资讯频道!

相关推荐: MongoDB Replica Sets该怎样搭建

本篇文章给大家分享的是有关MongoDB Replica Sets该怎样搭建,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。  无论我们学习什么语言,能打出一个HelloWorld成为了我们的第一步…

文章页内容下
赞(0) 打赏
版权声明:本站采用知识共享、学习交流,不允许用于商业用途;文章由发布者自行承担一切责任,与本站无关。
文章页正文下
文章页评论上

云服务器、web空间可免费试用

宝塔面板主机、支持php,mysql等,SSL部署;安全高速企业专供99.999%稳定,另有高防主机、不限制内容等类型,具体可咨询QQ:360163164,Tel同微信:18905205712

主机选购导航云服务器试用

登录

找回密码

注册