91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用MySQL MHA源代碼進行監控檢查

發布時間:2021-10-11 10:21:30 來源:億速云 閱讀:109 作者:柒染 欄目:MySQL數據庫


本篇文章給大家分享的是有關如何使用MySQL MHA源代碼進行監控檢查,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

一、前言

在研究的同時,把MHA的源代碼也翻閱了一遍,現在準備把MHA一些重要內容梳理一下,既然是高可用工具,那么健康檢測是一個基礎工作,只有正確檢測了數據庫的故障,才能進行數據庫的切換;而MHA的布局亦如此:

如何使用MySQL MHA源代碼進行監控檢查

二、MHA健康檢查核心調用函數鏈

    注意我這里的函數調用鏈的規則是文件名|方法名,方法名中的或者表示的是,通過讀取配置文件,執行其中的一個函數

    MasterMonitor.pm|MHA::MasterMonitor::main()

        ->MasterMonitor.pm|MHA::MasterMonitor::wait_until_master_is_dead()

            ->MasterMonitor.pm|MHA::MasterMonitor::wait_until_master_is_unreachable()

                ->HealthCheck.pm|MHA::HealthCheck::wait_until_unreachable()

                    ->HealthCheck.pm|MHA::HealthCheck::ping_select(或者)

                    ->HealthCheck.pm|MHA::HealthCheck::ping_insert(或者)

                    ->HealthCheck.pm|MHA::HealthCheck::ping_connect(或者)

三、代碼分析

    我們主要看HealthCheck.pm|MHA::HealthCheck::wait_until_unreachable的實現

    1) 該函數通過一個死循環,檢測4次,每次sleep ping_interval秒(這個值在配置文件指定,參數是ping_interval),持續四次失敗,就認為數據已經宕機

    2)如果有二路檢測腳本,需要二路檢測腳本檢測主庫宕機,才是真正的宕機,否則只是推出死循環,結束檢測,不切換

    3)這里的GETLOCK(姑且說是分布式鎖)就是用來保護數據庫的訪問,防止腳本多次啟動的

    4)該函數調用了三種經檢測方法,如下:

    PING_TYPE_CONNECT(ping_select),PING_TYPE_INSERT(ping_insert),PING_TYPE_SELECT(ping select),但是哪種最好呢,我建議是PING_TYPE_CONNECT,實際上PING_TYPE_CONNECT調用了ping_select的方法,比PING_TYPE_CONNECT更具有可靠性

# main function
# 返回1,表示數據庫有問題,但是不會切換;0表示數據庫有問題,會切換(這里同時還會返回ssh連接狀態,方便確認是網絡問題,還是數據庫問題)
sub wait_until_unreachable($) {
  my $self           = shift;
  my $log            = $self->{logger};
  my $ssh_reachable  = 2;
  my $error_count    = 0;
  my $master_is_down = 0;
  eval {
    while (1) {
      $self->{_tstart} = [gettimeofday];
      if ( $self->{_need_reconnect} ) {
    #測試連接,連接正確返回0,否則返回1
    ##這里有分布式GetLOCK,如果有別的會話,獲取了分布式鎖失敗,也算連接不成功
        my ( $rc, $mysql_err ) =
          $self->connect( undef, undef, undef, undef, undef, $error_count );
        if ($rc) {
          #排除權限錯誤
          if ($mysql_err) {
            if (
          #在這里并不是不能訪問,可能只是權限錯誤
              grep ( $_ == $mysql_err, @MHA::ManagerConst::ALIVE_ERROR_CODES )
              > 0 )
            {
              $log->info(
"Got MySQL error $mysql_err, but this is not a MySQL crash. Continue health check.."
              );
          #sleep一段時間
              $self->sleep_until();
          #好吧,如果是權限錯誤的話,就一直在這里循環了,那么檢測一致認為mysql正常,打印權限日志就行
              next;
            }
          }
          $error_count++;
          $log->warning("Connection failed $error_count time(s)..");
          #處理失敗,更新status_file為20:PING_FAILING
          $self->handle_failing();
      #超過四次就跳出這個循環了
          if ( $error_count >= 4 ) {
        #返回1表示ssh可以可以到達,0表示ssh不能到達
            $ssh_reachable = $self->is_ssh_reachable();
        #返回為1表示數據庫主庫已經down,0則沒有down
            $master_is_down = 1 if ( $self->is_secondary_down() );
        #退出循環,last
            last if ($master_is_down);
            $error_count = 0;
          }
          $self->sleep_until();
          next;
        }
        # connection ok
        $self->{_need_reconnect} = 0;
        $log->info(
"Ping($self->{ping_type}) succeeded, waiting until MySQL doesn't respond.."
        );
      }
      #釋放連接,如果只是類型為PING_TYPE_CONNECT
      $self->disconnect_if()
        if ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_CONNECT );
      # Parent process forks one child process. The child process queries
      # from MySQL every <interval> seconds. The child process may hang on
      # executing queries.
      # DBD::mysql 4.022 or earlier does not have an option to set
      # read timeout, executing queries might take forever. To avoid this,
      # the parent process kills the child process if it won't exit within
      # <interval> seconds.
      my $child_exit_code;
      eval {
        if ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_CONNECT ) {
          $child_exit_code = $self->fork_exec( sub { $self->ping_connect() },
            "MySQL Ping($self->{ping_type})" );
        }
        elsif ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_SELECT ) {
          $child_exit_code = $self->fork_exec( sub { $self->ping_select() },
            "MySQL Ping($self->{ping_type})" );
        }
        elsif ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_INSERT ) {
          $child_exit_code = $self->fork_exec( sub { $self->ping_insert() },
            "MySQL Ping($self->{ping_type})" );
        }
        else {
          die "Not supported ping_type!\n";
        }
      };
      if ($@) {
        my $msg = "Unexpected error heppened when pinging! $@";
        $log->error($msg);
        undef $@;
        $child_exit_code = 1;
      }
      if ( $child_exit_code == 0 ) {
        #ping ok
        #ping是成功的話,則更新狀態,然后將$error_count=0(持續累積4次,那就是連接有問題)
        $self->update_status_ok();
        if ( $error_count > 0 ) {
          $error_count = 0;
        }
    #handle_failing啟用了二路檢測以及ssh_check這時候沒結束需要kill掉
        $self->kill_sec_check();
        $self->kill_ssh_check();
      }
      #存在其他分布式監控
      elsif ( $child_exit_code == 2 ) {
        $self->{_already_monitored} = 1;
        croak;
      }
      else {
        # failed on fork_exec
        $error_count++;
        $self->{_need_reconnect} = 1;
        $self->handle_failing();
      }
      $self->sleep_until();
    }
    $log->warning("Master is not reachable from health checker!");
  };
  if ($@) {
    my $msg = "Got error when monitoring master: $@";
    $log->warning($msg);
    undef $@;
    return 2 if ( $self->{_already_monitored} );
    return 1;
  }
  #$master_is_down=0,返回1
  return 1 unless ($master_is_down);
   #0,$ssh_reachable返回1表示ssh可以可以到達,0表示ssh不能到達
  return ( 0, $ssh_reachable );
}
1;
三種檢測機制函數
#這個ping_connect正常返回0,錯誤返回1或者2,1是連接存在問題,2是獲取鎖失敗
#改函數調用了ping_select
sub ping_connect($) {
  my $self = shift;
  my $log  = $self->{logger};
  my $dbh;
  my $rc          = 1;
  my $max_retries = 2;
  eval {
    my $ping_start = [gettimeofday];
    #連接max_retries次,如果有錯誤,則退出
    while ( !$self->{dbh} && $max_retries-- ) {
      eval { $rc = $self->connect( 1, $self->{interval}, 0, 0, 1 ); };
      if ( !$self->{dbh} && $@ ) {
        die $@ if ( !$max_retries );
      }
    }
    #ping_select()正常返回為0,錯誤返回為1
    $rc = $self->ping_select();
    # To hold advisory lock for some periods of time
    #獲取鎖可能需要一定時間,所以在釋放連接之前,需要等待一點時間
    $self->sleep_until( $ping_start, $self->{interval} - 1.5 );
    $self->disconnect_if();
  };
  if ($@) {
    my $msg = "Got error on MySQL connect ping: $@";
    undef $@;
    $msg .= $DBI::err if ($DBI::err);
    $msg .= " ($DBI::errstr)" if ($DBI::errstr);
    $log->warning($msg) if ($log);
    $rc = 1;
  }
  return 2 if ( $self->{_already_monitored} );
  return $rc;
}
#語句SELECT 1 As Value,正常返回0,錯誤返回為1
sub ping_select($) {
  my $self = shift;
  my $log  = $self->{logger};
  my $dbh  = $self->{dbh};
  my ( $query, $sth, $href );
  eval {
    $dbh->{RaiseError} = 1;
    $sth = $dbh->prepare("SELECT 1 As Value");
    $sth->execute();
    $href = $sth->fetchrow_hashref;
    if ( !defined($href)
      || !defined( $href->{Value} )
      || $href->{Value} != 1 )
    {
      die;
    }
  };
  if ($@) {
    my $msg = "Got error on MySQL select ping: ";
    undef $@;
    $msg .= $DBI::err if ($DBI::err);
    $msg .= " ($DBI::errstr)" if ($DBI::errstr);
    $log->warning($msg) if ($log);
    return 1;
  }
  return 0;
}
#正常返回0,錯誤返回1,有個疑問,這里見得數據庫表貌似沒有清理吧
sub ping_insert($) {
  my $self = shift;
  my $log  = $self->{logger};
  my $dbh  = $self->{dbh};
  my ( $query, $sth, $href );
  eval {
    $dbh->{RaiseError} = 1;
    $dbh->do("CREATE DATABASE IF NOT EXISTS infra");
    $dbh->do(
"CREATE TABLE IF NOT EXISTS infra.chk_masterha (`key` tinyint NOT NULL primary key,`val` int(10) unsigned NOT NULL DEFAULT '0') engine=MyISAM"
    );
    $dbh->do(
"INSERT INTO infra.chk_masterha values (1,unix_timestamp()) ON DUPLICATE KEY UPDATE val=unix_timestamp()"
    );
  };
  if ($@) {
    my $msg = "Got error on MySQL insert ping: ";
    undef $@;
    $msg .= $DBI::err if ($DBI::err);
    $msg .= " ($DBI::errstr)" if ($DBI::errstr);
    $log->warning($msg) if ($log);
    return 1;
  }
  return 0;
}

四、總結

    1)數據庫MHA的健康檢查,最終調用的ping_select,ping_insert,ping_connect的一種,檢測的時間由ping_interval控制,其中ping_connect調用了ping_select

    2)MHA最好配置二路檢測,否則只是MHA主節點從自身ssh去檢測主庫是否正常,在MHA管理節點與主庫網絡存在問題的時候,有可能會發生誤切換

    3)注意:這里只列出了核心函數,其實在程序啟動的時候,還有一些啟動情況檢查,基本是主庫是否可連接,配置是否正確,從庫是否正常等等

以上就是如何使用MySQL MHA源代碼進行監控檢查,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

集贤县| 封开县| 蒙自县| 阜新市| 黄山市| 扎鲁特旗| 汾阳市| 江华| 河源市| 崇明县| 呈贡县| 旌德县| 佛教| 海安县| 江口县| 兴安盟| 鄂州市| 桐梓县| 革吉县| 墨竹工卡县| 金阳县| 贵州省| 小金县| 墨脱县| 丰顺县| 长兴县| 屯留县| 满城县| 巧家县| 上蔡县| 新民市| 循化| 崇左市| 莆田市| 大厂| 姚安县| 常熟市| 习水县| 锡林浩特市| 山丹县| 东乡县|