MySQL:MGR节点上线恢复简析


仅仅作为自己的学习笔记,不做其他用途。


一、恢复的主要阶段

实际上节点的加入会经历几个主要的流程

  • 发起一个Control_notification调用Gcs_xcom_control::retry_do_join连接到种子节点,
    发送加入的请求给xcom线程,xom线程检测到有节点加入后,然后由xcom线程下发Global_view_notification给各个节点(包括加入节点)表示有节点申请加入。
  • 各个节点收到Global_view_notification的消息后,获取本节点的一些信息,比如本节点执行的gtid信息、视图更新后的节点信息等。完成后发送一个信息给xcom线程
    (Cargo_type::CT_INTERNAL_STATE_EXCHANGE)
  • xcom线程下发Data_notification ,交由xcom engine线程处理,主要就是安装视图
  1. 对于现有节点而言,主要更新视图信息,将加入节点的状态更改为recovery
  2. 对于加入节点而言,也是先将自己的状态设置为recovery然后进行恢复。
  • 加入节点恢复完成后,会发送online消息给各个节点,各个节点将节点状态状态
    设置为online。

在加入的过程中视图版本会加1,由于view change event会封装在一个事务里面,因此
GTID也会加1,封装的过程主要处于Certification_handler::handle_event中对于view change event的处理。

二、加入阶段数据恢复的简图

这里我们主要看看加入节点的恢复流程,这里主要涉及到3个线程的协同工作,用图表示:

未命名文件.jpg

本处小结:

  • clone插件只有在GTID差值超过group_replication_clone_threshold参数设置或者恢复库需要的GTID已经在所有节点都清理了才会启用
  • 节点处于recovery状态是比较早的,如果其中流程出错,看到的视图信息依旧是recovery,比如选择donor节点恢复出现问题,这是常见的。
  • 节点上线依赖参数group_replication_recovery_complete_at的设置,默认设置为TRANSACTIONS_APPLIED,如果有大量的事务应用,那么节点上线可能推迟,因此加入节点选择低峰期进行
  • incoming队列的缓存的是否如果过多,可能出现问题。因此加入节点选择低峰期。

三、代码部分笔记


Gcs_xcom_control::process_control_message
  视图版本+1
  ->Gcs_xcom_control::install_view
    根据新的节点信息建立新的视图
   ->Plugin_gcs_events_handler::on_view_changed
    ->Plugin_gcs_events_handler::handle_joining_members
     -> is_joining == ture
       先学习这个分支
       ->状态在恢复当中 MEMBER_IN_RECOVERY
       update_member_status(
        new_view.get_joined_members(), Group_member_info::MEMBER_IN_RECOVERY,
        Group_member_info::MEMBER_OFFLINE, Group_member_info::MEMBER_END);
       
       ->设置super read only  如果设置出错
       enable_server_read_mode(PSESSION_DEDICATED_THREAD)
       ->如果是多主需要考虑自增是否符合要求
       new_view.get_members().size() > auto_increment_increment
        挂起applier通道----->applier通道处于挂起状态
       ->根据下发的view id进行View_change_packet的构建,并且推送给
         applier通道的pipeline 进行处理 Applier_module.add_view_change_packet 
         View_change_packet *view_change_packet = new View_change_packet(view_id);
         applier_module->add_view_change_packet(view_change_packet);
       ->进行恢复方式的选择
        ->是否使用clone
          recovery_strategy = remote_clone_handler->check_clone_preconditions();
          ->这里根据参数来判定,到底是使用clone还是recovery的方式
       ->如果是clone则新建clone线程
         remote_clone_handler->clone_server 先不考虑clone
       ->如果是recovery则新建recovery线程
         recovery_module->start_recovery(new_view.get_group_id().get_group_id(),new_view.get_view_id().get_representation())
         启动恢复线程,加入的是group id和view id
         见下面的流程
         

进行恢复
Recovery_module::start_recovery
   ->初始化group_name和view_id
     this->group_name = group_name;
     recovery_state_transfer.initialize(rec_view_id); 
   ->启动新线程
     ->launch_handler_thread
      ->handler->recovery_thread_handle()
      实际调用为Recovery_module::recovery_thread_handle
        ->step0
          
        ->step1
          applier_module->wait_for_applier_complete_suspension(&recovery_aborted);
          等待applier线程的SQL线程应用完现有的relay log的事务,等待是通过收到的GTID
          为最终等待的GTID,完成后进入下一步
        ->step2
          如果只有一个节点,直接进入上线流程,跳过步骤3
        ->step3
          进行recovery流程
          recovery_state_transfer.state_transfer(stage_handler); 
          ->establish_donor_connection
            建立donor的连接
           ->选择donor节点?这里看的和前期看的不同,需要确认
             这里暴露了一些构建的方法,比如必须是online。
           ->尝试连接donor节点,并且进行不同的报错
             initialize_donor_connection
           ->进行恢复
             start_recovery_donor_threads
             这里带入了view_id,也就是进行恢复结束的位置为view change event的来到
             ->donor_connection_interface.start_threads(true, true, &view_id, true);
        ->step4     
           ->applier_module->awake_applier_module();
             唤醒apllier通道继续应用缓存的event,这里前面挂起了applier通道,只是event和消息
             缓存到了incoming队列。!!!!
           ->Recovery_module::wait_for_applier_module_recovery
             等待上线,开启循环
             while (!recovery_aborted && applier_monitoring)
             ->获取incoming 队列大小
               applier_module->get_message_queue_size();
             ->获取每秒恢复应用事务的数量
             ->如果参数设置为 cerify,则上线条件为
               ->恢复期间认证为0则继续进行处理
                 根据需要认证的事务总数和已经认证的事务数量进行统计,其中已经认证的事务数量在Certifier::certify的末尾进行增加。
             ->如果参数设置为applier,则上线条件为
               ->1.如果剩余需要过pipeline流程的事务,数量少于每秒恢复的事务数量,说明已经很少了,下一秒即可执行完成
               ->2.如果incoming队列为0 、每秒恢复的事务数量为0 、applier的SQL线程处于空闲状态了
                 如果满足上面其中一个1个条件,进入等待,等待为接受的GTID全部应用完成。
             ->如果不满足上面的条件则进行循环等待
               否则进行睡眠 incoming队列大小有关,但最大睡眠 为 100*5000 微秒
               
         ->step5 
          ->发送节点恢复完成的消息
           notify_group_recovery_end();
           这个消息是发给xcom的,因此是全员消息,应该是通知各个节点更改本节点状态为online
         ->step7
           终止recovery线程
             
             
            
             
applier_module->add_view_change_packet(view_change_packet);       
   xcom engine推送view change packet给 applier进行pipeline处理
    
Applier_module::applier_thread_handle
   -> packet_application_error = apply_view_change_packet((View_change_packet *)packet, fde_evt, cont);
    -> Applier_module::apply_view_change_packet
      -> Applier_module::inject_event_into_pipeline
        ->Event_cataloger::handle_event
          ->Event_handler::next
            ->Certification_handler::handle_event
              -> Certification_handler::extract_certification_info
                ->Certification_handler::log_view_change_event_in_order
                  ->Certification_handler::inject_transactional_events
                     生成一个gtid事务,包含事务的所有event,并且会分配gtid
                     ->Event_handler::next

参考:
https://zhuanlan.zhihu.com/p/40627399

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352