千家信息网

【MySQL】MHA源代码之主库选取(二)

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,一 、MHA 选举主库所维护的数组在讲MHA选择 master的代码中,我们必须把维护的四个数组的来龙去脉讲清楚(1) Alive_slaves 数组 :server不是 master,且从库正常,
千家信息网最后更新 2026年11月01日【MySQL】MHA源代码之主库选取(二)

一 、MHA 选举主库所维护的数组

在讲MHA选择 master的代码中,我们必须把维护的四个数组的来龙去脉讲清楚

(1) Alive_slaves 数组 :

server不是 master,且从库正常, latest数组中的 server有足够的中继日志恢复这个落后的从库 (追上主库 ),则放入这个 Alive_slaves的数组中 (此段代码在 ServerManager.pm: init_servers函数 )

    if ( $server->{dead} ) {      $self->add_dead_server($server);    }    elsif ( $server->{unmanaged} ) {      $self->add_unmanaged_slave($server);    }    #不是dead或者unmanaged就加入alive_server数组,如果show slave status 不是返回0E0,且这个server不是原来的主库,并且sql线程无误且可以用中继日志来恢复,就加入alive_slave数据,否则加入failed--slave数组    else {      $self->add_alive_server($server);      if ( $server->{not_slave} eq '0' && !$server->{orig_master} ) {        if ( !$server->is_sql_thread_error() && !$server->{lack_relay_log} ) {          $self->add_alive_slave($server);        }        else {          $self->add_failed_slave($server);        }      }}

(2)Latest 数组

在 alive_slaves数组中选取 relaylog最新的 server,这个数组如果有多个 server,则 server的 Read_master_log_pos,master_log_file一定相等(此段代码在 ServerManager.pm: identify_latest_slaves函数)

 my @slaves = $self->get_alive_slaves();  my @latest = ();  foreach (@slaves) {    my $a = $latest[0]{Master_Log_File};    my $b = $latest[0]{Read_Master_Log_Pos};    if (      #find_oldest=0,即我们取的最全relaylog的slave,至于这里为什么是数组,是因为有最新的relaylog的不只有一个,可能有多个((即数组里边边的slave,具有一样的Read_Master_Log_     Pos位置))      !$find_oldest      && (           ( !$a && !defined($b) )        || ( $_->{Master_Log_File} gt $latest[0]{Master_Log_File} )        || ( ( $_->{Master_Log_File} ge $latest[0]{Master_Log_File} )          && $_->{Read_Master_Log_Pos} > $latest[0]{Read_Master_Log_Pos} )      )      )    {      @latest = ();      push( @latest, $_ );}

(3)Perf 数组

这个无需多解释,就是MHA配置文件中配置了 candidate_master的值,这个可以大于 1哦

(4)Bad 数组: ( 代码见: ServerManager.pm:get_bad_candidate_masters)

1) 检测有故障的server

2) MHA 配置文件设置了 no_master 的 server

3)log_bin 没有打开的server

4) 版本不兼容的server (高版本复制到低版本是没问题的,但是如果低版本的选为为主库,嘿嘿)

5) 复制落后太多的server

二 、MHA 主库的选举

(1) 指定主库切换的,优先级最高(通常这是在手动切换)

(2) 如果server 在 latest 数组中,且在 perf 数组中,则优先返回

(3) 如果server 在 alive_servers 数组中,且在 perf 数组中,则优先返回

(4) 如果server 在 lastest 中,则优先返回

(5) 如果server 在 alive_servers 中,则返回

(6) 否则选举失败

这里优先级为1->6,具体实现在 (ServerManager.pm: select_new_master)

sub select_new_master {  my $self                    = shift;  my $prio_new_master_host    = shift;  my $prio_new_master_port    = shift;  my $check_replication_delay = shift;  $check_replication_delay = 1 if ( !defined($check_replication_delay) );   my $log    = $self->{logger};  my @latest = $self->get_latest_slaves();  my @slaves = $self->get_alive_slaves();   my @pref = $self->get_candidate_masters();  my @bad =    $self->get_bad_candidate_masters( $latest[0], $check_replication_delay );  #切换指定了master,即优先级最高的  if ( $prio_new_master_host && $prio_new_master_port ) {    my $new_master =      $self->get_alive_server_by_hostport( $prio_new_master_host,      $prio_new_master_port );    if ($new_master) {      my $a = $self->get_server_from_by_id( \@bad, $new_master->{id} );      unless ($a) {        $log->info("$prio_new_master_host can be new master.");        return $new_master;      }      else {        $log->error("$prio_new_master_host is bad as a new master!");        return;      }    }    else {      $log->error("$prio_new_master_host is not alive!");      return;    }  }   $log->info("Searching new master from slaves..");  $log->info(" Candidate masters from the configuration file:");  $self->print_servers( \@pref );  $log->info(" Non-candidate masters:");  $self->print_servers( \@bad );  #如果perf(candidate_master没设置)以及没有不符合(主从延迟,版本等)的slave,并且lastest[0]设置有优先级的话,就返回  return $latest[0]    if ( $#pref < 0 && $#bad < 0 && $latest[0]->{latest_priority} );  #如果设置了优先级,则从lastest数组中选择是canidate_master的,有就返回(隐含lastest[0]优先,如果lastest[0]同时是canidate_master,那肯定是优先返回的)  #latest_priority默认设置为1  if ( $latest[0]->{latest_priority} ) {    $log->info(" Searching from candidate_master slaves which have received the latest relay log events.."    ) if ( $#pref >= 0 );    foreach my $h (@latest) {      foreach my $p (@pref) {        if ( $h->{id} eq $p->{id} ) {          return $h            if ( !$self->get_server_from_by_id( \@bad, $p->{id} ) );        }      }    }    $log->info("  Not found.") if ( $#pref >= 0 );  }   #new master is not latest  #这里选择的是candidate_master,单不是latest数组中的master  $log->info(" Searching from all candidate_master slaves..")    if ( $#pref >= 0 );  foreach my $s (@slaves) {    foreach my $p (@pref) {      if ( $s->{id} eq $p->{id} ) {        my $a = $self->get_server_from_by_id( \@bad, $p->{id} );        return $s unless ($a);      }    }  }  $log->info("  Not found.") if ( $#pref >= 0 );  #其次是优先在lastest数组中,但不在candidate_master中的  if ( $latest[0]->{latest_priority} ) {    $log->info(" Searching from all slaves which have received the latest relay log events.."    );    foreach my $h (@latest) {      my $a = $self->get_server_from_by_id( \@bad, $h->{id} );      return $h unless ($a);    }    $log->info("  Not found.");  }   # none of latest servers can not be a master  $log->info(" Searching from all slaves..");  foreach my $s (@slaves) {    my $a = $self->get_server_from_by_id( \@bad, $s->{id} );    return $s unless ($a);  }  $log->info("  Not found.");   return;}


数组 优先级 版本 代码 切换 选举 选择 配置 最高 函数 多个 文件 日志 落后 中继 最全 来龙去脉 个数 主从 位置 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 有格互联网科技 上海喔噻互联网科技有限公司 互联网是第几次科技革命的成果 广州万易互联网科技有限公司 互联网科技深圳 艾特科技互联网 衡水科技产业互联网平台 中国最先进互联网科技公司 济南和联互联网科技有限公司 隆华科技工业互联网 哈尔滨新华互联网科技学院 国大互联网教育科技有限公司工作 河南住房之家互联网科技 迪庆互联网科技招生 互联网科技创新的路径 互联网第三次科技革命特征 半导体行业属于互联网高科技类吗 湖北辰鑫科技互联网 广州智享互联网科技 保山浩联互联网科技有限公司 精品咖啡豆 互联网科技工作委员会副主任毛军 互联网与未来科技 天速互联网络科技有限公司 互联网与医疗科技 爱医互联网络科技 南博望互联网科技有限公司 互联网第三次科技革命特征 上海乐五互联网科技有限公司 互联网科技企业文化
0