美文网首页DBA
MHA在启用GTID的MySQL集群丢数据的问题

MHA在启用GTID的MySQL集群丢数据的问题

作者: mysia | 来源:发表于2020-05-19 20:06 被阅读0次

今天有朋友咨询我MySQL高可用方案MHA的事情,恰好之前在公司改造过MHA,看过MHA的代码,解答了朋友的问题,在这里也分享一下经验。

MHA使用Perl语言编写,本文尽量不涉及语法,直观讲解。

MHA作为业界内火了十几年的MySQL高可用方案,必然有他的过人之处。在传统的MySQL复制模式下(文件 + 点位),MHA可以追补relay log,可以重放差异的binlog,还有丰富的工具支持,在当时看来,基本上无懈可击。

但是随着MySQL版本的迭代,GTID横空出世。虽然MHA也可在启用GTID的MySQL集群中使用,但是第一个坑就出现了。

直接上代码:

    $log->info("* Phase 3: Master Recovery Phase..\n");
    $log->info();

    $log->info("* Phase 3.1: Getting Latest Slaves Phase..\n");
    $log->info();
    check_set_latest_slaves();

    if ( !$_server_manager->is_gtid_auto_pos_enabled() ) {
      $log->info();
      $log->info("* Phase 3.2: Saving Dead Master's Binlog Phase..\n");
      $log->info();
      save_master_binlog($dead_master);
    }

    $log->info();
    $log->info("* Phase 3.3: Determining New Master Phase..\n");
    $log->info();

    my $latest_base_slave;
    if ( $_server_manager->is_gtid_auto_pos_enabled() ) {
      $latest_base_slave = $_server_manager->get_most_advanced_latest_slave();
    }
    else {
      $latest_base_slave = find_latest_base_slave($dead_master);
    }
    $new_master = select_new_master( $dead_master, $latest_base_slave );

    my $start_failover_subject = "Start Failover";
    send_report($dead_master, $new_master, $start_failover_subject);

    my ( $master_log_file, $master_log_pos, $exec_gtid_set ) =
      recover_master( $dead_master, $new_master, $latest_base_slave,
      $binlog_server_ref );
    $new_master->{activated} = 1;

    $log->info("* Phase 3: Master Recovery Phase completed.\n");

从上述代码中可以看出,如果没有启用GTID,也就是!$_server_manager->is_gtid_auto_pos_enabled(),会保存原主库的binlog,也就是save_master_binlog($dead_master)函数。如果启用了GTID呢,就进入了选主阶段,并没有保存原主库的binlog。

那么问题来了,假设一套启用了GTID的MySQL集群,所有从库都有延时,这时候主库宕机,就出现了我朋友的问题,切换过程中会丢失数据

如果丢失数据,那MHA岂不是不可靠了吗?

其实不然,上述问题可解。在上面代码的最后,是在补新主库($new_master)和原主库($dead_master)的差异数据。调用的函数为recover_master( $dead_master, $new_master, $latest_base_slave,$binlog_server_ref )。在这个函数中,穿入的参数$binlog_server_ref,就是上面问题的解,下面上论据。

我们先看一下recover_master这个函数

sub recover_master($$$$) {
...
  my ( $master_log_file, $master_log_pos, $exec_gtid_set );
  if ( $_server_manager->is_gtid_auto_pos_enabled() ) {
    ( $master_log_file, $master_log_pos, $exec_gtid_set ) =
      recover_master_gtid_internal( $new_master, $latest_base_slave,
      $binlog_server_ref );
  }
  else {
    ( $master_log_file, $master_log_pos ) =
      recover_master_internal( $new_master, $latest_base_slave );
  }
  ...
  return ( $master_log_file, $master_log_pos, $exec_gtid_set );
}

这里只提取了恢复新主库和原主库差异binlog相关的部分。可以看到,如果启用了GTID($_server_manager->is_gtid_auto_pos_enabled()),那么调用recover_master_gtid_internal( $new_master, $latest_base_slave,$binlog_server_ref );;否则会调用recover_master_internal( $new_master, $latest_base_slave )。从这里可以看出,如果启用GTID,调用的函数中的参数有$binlog_server_ref,也就是binlog server的相关配置。

我们继续看被调用的函数recover_master_gtid_internal

sub recover_master_gtid_internal($$$) {
  ...
  if (
    save_from_binlog_server(
      $relay_master_log_file, $exec_master_log_pos, $binlog_server_ref
    )
    )
  {
    apply_binlog_to_master($target);
  }
  return $_server_manager->get_new_master_binlog_position($target);
}

上面代码中,略去了补relay log和change master部分。可以看出,如果启用了$binlog_server_ref,则会调用apply_binlog_to_master来补binlog。apply_binlog_to_master这个函数就不展开了,大致过程就是调用save_binary_logs把binlog server的binlog拉取到本地,然后在新主库上回放。

综上,在启用GTID的MySQL集群上部署MHA,必须额外增加binlog server,来解决延时带来的数据丢失隐患。

注意,binlog server的原理也是采用mysqlbinlog模拟一个从库来保存binlog日志,因此binlog server的配置要>= slaves。

聊到这里,朋友的问题已经解答完毕,至于如何在MHA中配置binlog server,我让他自行百度去了。

后面,我们又聊了一下MySQL 8.x中能否使用MHA?答案是可以的。(这里不做MGR和MHA的比较,只讨论可行性)。MySQL 8.x在使用MHA时有哪些问题,参考这里

相关文章

  • MHA在启用GTID的MySQL集群丢数据的问题

    今天有朋友咨询我MySQL高可用方案MHA的事情,恰好之前在公司改造过MHA,看过MHA的代码,解答了朋友的问题,...

  • 13 MySQL MHA集群

    MySQL MHA 集群 [toc] MHA 简介 MHA ( Master High Availability ...

  • MySQL MHA

    MySQL-day16 MHA切换优先级 在数据量相同的情况下,MHA会往哪里切换? MHA启动命令 MHA集群恢...

  • MYSQL--进阶

    MYSQL主从复制 类别 基于日志点的复制支持MMM和MHA架构 基于GTID方式的复制GTID= source_...

  • MySQL集群

    MyAQL常用的集群: mysql cluster,nbd,MHA,Mariadb Galera cluster,...

  • MySQL MHA+GTID

    MySQL环境准备 主机名wanIPlanIP角色db0110.0.0.51172.16.1.51主库,MHA客户...

  • 搭建MHA的必备需求

    一. SSH public key authentication MHA manager连接mysql集群各实例是...

  • MySQL复制和GTID

    本文问题 在使用GTID的MySQL复制中,如何判断主从是否一致? mysql.gtid_executed表是哪个...

  • MySQL MHA搭建

    MySQL MHA 架构介绍:MHA由两部分组成MHA Manager(管理节点)和MHA Node(数据节点),...

  • Mysql8 MHA高可用搭建之MHA安装配置及测试

    三、mysql8基于MHA的高可用集群0、配置ssh密钥登入各服务器互信:1、安装MHA软件2、安装mha监控ma...

网友评论

    本文标题:MHA在启用GTID的MySQL集群丢数据的问题

    本文链接:https://www.haomeiwen.com/subject/gyciohtx.html