• ADADADADAD

    Mysql 5.7中Gtid和Last_commt/sequnce_number的生成时机是什么[ mysql数据库 ]

    mysql数据库 时间:2024-11-26 22:11:55

    作者:文/会员上传

    简介:

    一、Gtid生成类型这里首先使用源码的解释给出三种类型:AUTOMATIC_GROUPGTID_GROUPANONYMOUS_GROUP其中AUTOMATIC_GROUP通常用于主库开启Gtid的情况,GTID_GROUP通常用于备库和

    以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。

    一、Gtid生成类型

    这里首先使用源码的解释给出三种类型:

      AUTOMATIC_GROUP

      GTID_GROUP

      ANONYMOUS_GROUP

      其中AUTOMATIC_GROUP通常用于主库开启Gtid的情况,GTID_GROUP通常用于备库和使用了GTID_NEXT的情况下。

      源码中有详细解释如下:

      /**SpecifiesthattheGTIDhasnotbeengeneratedyet;itwillbegeneratedoncommit.ItwilldependontheGTID_MODE:ifGTID_MODE<=OFF_PERMISSIVE,thenthetransactionwillbeanonymous;ifGTID_MODE>=ON_PERMISSIVE,thenthetransactionwillbeassignedanewGTID.Thisisthedefaultvalue:thd->variables.gtid_nexthasthisstatewhenGTID_NEXT="AUTOMATIC".ItisimportantthatAUTOMATIC_GROUP==0sothatthedefaultvalueforthd->variables->gtid_next.typeisAUTOMATIC_GROUP.*/AUTOMATIC_GROUP=0,/**SpecifiesthatthetransactionhasbeenassignedaGTID(UUID:NUMBER).thd->variables.gtid_nexthasthisstatewhenGTID_NEXT="UUID:NUMBER".ThisisthestateofGTID-transactionsreplicatedtotheslave.*/GTID_GROUP,/**Specifiesthatthetransactionisanonymous,i.e.,itdoesnothaveaGTIDandwillneverbeassignedone.thd->variables.gtid_nexthasthisstatewhenGTID_NEXT="ANONYMOUS".Thisisthestateofanytransactiongeneratedonapre-GTIDserver,oronaserverwithGTID_MODE==OFF.*/ANONYMOUS_GROUP
      二、Gtid和Last_commt/sequnce_number的生成时机

      Gtid其实是在commit的时候调用MYSQL_BIN_LOG::ordered_commit执行到flush 阶段产生Gtid event的时候才生成,生成后会将这个Gtid 加入到Gtid_state的Owned_gtids中,实际上这个过程不仅要生成Gtid还会生成sequence_number和last_commit并且会构造Gtid_event写入到binlog cache最后将binlog cache写入到binlog file,下面是binlog_cache_data::flush函数的片段:

      if(!error)if((error=mysql_bin_log.write_gtid(thd,this,&writer)))//生成Gtid和Last_commt/sequnce_number构造好Gtidevent并且写入到到binlogcache中thd->commit_error=THD::CE_FLUSH_ERROR;if(!error)error=mysql_bin_log.write_cache(thd,this,&writer);//将binlogcache写入到文件

      下面是mysql_bin_log.write_gtid中生成Gtid和Last_commt/sequnce_number的代码片段:

      if(thd->variables.gtid_next.type==AUTOMATIC_GROUP)//如果过是非指定的Gtid则需要自动生成调用generate_automatic_gtid生成{if(gtid_state->generate_automatic_gtid(thd,thd->get_transaction()->get_rpl_transaction_ctx()->get_sidno(),thd->get_transaction()->get_rpl_transaction_ctx()->get_gno())!=RETURN_STATUS_OK)DBUG_RETURN(true);}.....//下面生成sequence_number和last_committedint64relative_sequence_number=trn_ctx->sequence_number-clock.get_offset();int64relative_last_committed=trn_ctx->last_committed<=clock.get_offset()?SEQ_UNINIT:trn_ctx->last_committed-clock.get_offset();

      其调用栈帧如下:

      #0Gtid_state::get_automatic_gno(this=0x2ff8bb0,sidno=1)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:564#10x0000000001803248inGtid_state::generate_automatic_gtid(this=0x2ff8bb0,thd=0x7fff2c000b70,specified_sidno=0,specified_gno=0)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:628#20x0000000001845703inMYSQL_BIN_LOG::write_gtid(this=0x2dffc80,thd=0x7fff2c000b70,cache_data=0x7fff2c021178,writer=0x7ffff0358810)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:1167#30x0000000001846307inbinlog_cache_data::flush(this=0x7fff2c021178,thd=0x7fff2c000b70,bytes_written=0x7ffff03588b8,wrote_xid=0x7ffff0358917)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:1454#40x0000000001860e57inbinlog_cache_mngr::flush(this=0x7fff2c020ff0,thd=0x7fff2c000b70,bytes_written=0x7ffff0358918,wrote_xid=0x7ffff0358917)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:768#50x0000000001856d46inMYSQL_BIN_LOG::flush_thread_caches(this=0x2dffc80,thd=0x7fff2c000b70)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8470#60x0000000001856f77inMYSQL_BIN_LOG::process_flush_stage_queue(this=0x2dffc80,total_bytes_var=0x7ffff0358a88,rotate_var=0x7ffff0358a87,out_queue_var=0x7ffff0358a78)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8532#70x0000000001858593inMYSQL_BIN_LOG::ordered_commit(this=0x2dffc80,thd=0x7fff2c000b70,all=false,skip_commit=false)

      接下来我们就需要具体研究下一个Gtid是依靠什么逻辑生成的。我们需要查看函数Gtid_state::generate_automatic_gtid和Gtid_state::get_automatic_gno逻辑,他们用于生成一个Gtid。

      三、Gtid_state::generate_automatic_gtid逻辑
      //IfGTID_MODE=ON_PERMISSIVEorON,generateanewGTIDif(get_gtid_mode(GTID_MODE_LOCK_SID)>=GTID_MODE_ON_PERMISSIVE)//如果GTID_MODE是ON_PERMISSIVE和ON则生成GTID{Gtidautomatic_gtid={specified_sidno,specified_gno};if(automatic_gtid.sidno==0)//如果是备库则sidno>0,如果是主库sidno==0,因为主库的Gtid这个时候才生成,但是备库则是使用GTID_GROUP指定生成automatic_gtid.sidno=get_server_sidno();//此处返回本server的sidnolock_sidno(automatic_gtid.sidno);//此处对并发生成GNO的多个线程进行控制if(automatic_gtid.gno==0)//如果是备库则gno>0,如果是主库gno==0,因为主库的Gtid这个时候才生成,但是备库则是使用GTID_GROUP指定生成automatic_gtid.gno=get_automatic_gno(automatic_gtid.sidno);//此处返回最后指定sidno的endgnoif(automatic_gtid.gno!=-1)acquire_ownership(thd,automatic_gtid);//此处将这个gtid及上面的SIDNO:gno加入到owned_gtids中并且赋予给线程经过本步骤可以显示elseret=RETURN_STATUS_REPORTED_ERROR;unlock_sidno(automatic_gtid.sidno);//分配完成其他线程可以分配}else//如果是OFF_PERMISSIVE或者OFF状态如何处理这里不做讨论了{//IfGTID_MODE=OFForOFF_PERMISSIVE,justmarkthisthreadas//usingananonymoustransaction.thd->owned_gtid.sidno=THD::OWNED_SIDNO_ANONYMOUS;thd->owned_gtid.gno=0;acquire_anonymous_ownership();thd->owned_gtid.dbug_print(NULL,"setowned_gtid(anonymous)ingenerate_automatic_gtid");}sid_lock->unlock();//释放读写锁

      接下来看看gno的生成逻辑Gtid_state::get_automatic_gno。

      四、Gtid_state::generate_automatic_gtid逻辑
      while(true){constGtid_set::Interval*iv=ivit.get();//定义Interval指针指向这个链表指针开头,如果在进行下次循环会获得NULLrpl_gnonext_interval_start=iv!=NULL?iv->start:MAX_GNO;//正常情况下不会为NULL因此next_interval_start等于第一个interval的start,当然如果初始化会为NULL,//如果Interval->next=NULL则标示没有区间了。while(next_candidate.gno<next_interval_start&&DBUG_EVALUATE_IF("simulate_gno_exhausted",false,true))//这里next_candidate.gno正常不会小于next_interval_start,如果Interval->next=NULL或者初始化//next_interval_start会被制为MAX_GNO那么条件成立//DBUG_RETURN(next_candidate.gno);返回了这个gno则GTID生成{if(owned_gtids.get_owner(next_candidate)==0)//如果本GTID已经被其他线程占用则next_candidate.gno++;返回这个gno。DBUG_RETURN(next_candidate.gno);next_candidate.gno++;}if(iv==NULL||DBUG_EVALUATE_IF("simulate_gno_exhausted",true,false)){my_error(ER_GNO_EXHAUSTED,MYF(0));DBUG_RETURN(-1);}next_candidate.gno=iv->end;//iv->end则指向了本区间最大的值+1ivit.next();}
    Mysql 5.7中Gtid和Last_commt/sequnce_number的生成时机是什么.docx

    将本文的Word文档下载到电脑

    推荐度:

    下载
    热门标签: gtidmysql