MySQL MMM 数据不一致探究

slave重新指向新的master 的关键日志输出,通过这些日志输出,我们大致可以明白MMM自动failover或在线切换时的执行流程。

--自动failover,slave节点
2015/02/06 01:47:09  INFO Changing active master to 'raugherdb1'
2015/02/06 01:47:09 DEBUG Executing /usr/lib/MySQL-mmm//agent/set_active_master raugherdb1
2015/02/06 01:47:09 DEBUG Result: OK

--在线切换
--主1节点
2015/02/06 05:49:23 DEBUG Received Command SET_STATUS|1|raugherdb1|ONLINE|reader(10.5.6.103)|raugherdb2
2015/02/06 05:49:23  INFO We have some new roles added or old rules deleted!
2015/02/06 05:49:23  INFO Deleted: writer(10.5.6.100)
2015/02/06 05:49:23 DEBUG Executing /usr/lib/mysql-mmm//agent/mysql_deny_write 
2015/02/06 05:49:23 DEBUG Executing /usr/lib/mysql-mmm//agent/clear_ip eth0 10.5.6.100
 
--主2节点
2015/02/06 05:49:22 DEBUG Daemon: Command = 'SET_STATUS|1|raugherdb2|ONLINE|reader(10.5.6.101),writer(10.5.6.100)|raugherdb2'
2015/02/06 05:49:22 DEBUG Received Command SET_STATUS|1|raugherdb2|ONLINE|reader(10.5.6.101),writer(10.5.6.100)|raugherdb2
2015/02/06 05:49:22  INFO We have some new roles added or old rules deleted!
2015/02/06 05:49:22  INFO Added:  writer(10.5.6.100)
2015/02/06 05:49:22 DEBUG Executing /usr/lib/mysql-mmm//agent/sync_with_master 
2015/02/06 05:49:23 DEBUG Executing /usr/lib/mysql-mmm//agent/mysql_allow_write 
2015/02/06 05:49:23 DEBUG Executing /usr/lib/mysql-mmm//agent/configure_ip eth0 10.5.6.100
 
--slave节点
2015/02/06 05:49:22 DEBUG Daemon: Command = 'SET_STATUS|1|raugherdb|ONLINE|reader(10.5.6.102)|raugherdb2'
2015/02/06 05:49:22 DEBUG Received Command SET_STATUS|1|raugherdb|ONLINE|reader(10.5.6.102)|raugherdb2
2015/02/06 05:49:22  INFO Changing active master to 'raugherdb2'
2015/02/06 05:49:22 DEBUG Executing /usr/lib/mysql-mmm//agent/set_active_master raugherdb2
2015/02/06 05:49:23 DEBUG Result: OK

以下是set_active_master方法的代码:

sub set_active_master($) {
    my $new_peer = shift;
    _exit_error('Name of new master is missing') unless (defined($new_peer));
 
    my $this = _get_this();
 
    _exit_error('New master is equal to local host!?') if ($this eq $new_peer);
 
    # Get local connection info
    my ($this_host, $this_port, $this_user, $this_password) = _get_connection_info($this);
    _exit_error("No connection info for local host '$this_host'") unless defined($this_host);
     
    # Get connection info for new peer
    my ($new_peer_host, $new_peer_port, $new_peer_user, $new_peer_password) = _get_connection_info($new_peer);
    _exit_error("No connection info for new peer '$new_peer'") unless defined($new_peer_host);
     
    # Connect to local server
    my $this_dbh = _mysql_connect($this_host, $this_port, $this_user, $this_password);
    _exit_error("Can't connect to MySQL (host = $this_host:$this_port, user = $this_user)! " . $DBI::errstr) unless ($this_dbh);
 
    # Get slave info
    my $slave_status = $this_dbh->selectrow_hashref('SHOW SLAVE STATUS');
    _exit_error('SQL Query Error: ' . $this_dbh->errstr) unless defined($slave_status);
 
    my $wait_log  = $slave_status->{Master_Log_File};
    my $wait_pos  = $slave_status->{Read_Master_Log_Pos};
 
    my $old_peer_ip    = $slave_status->{Master_Host};
    _exit_error('No ip for old peer') unless ($old_peer_ip);
 
    # Get connection info for old peer
    my $old_peer = _find_host_by_ip($old_peer_ip);
    _exit_error('Invalid master host in show slave status') unless ($old_peer);
 
    _exit_ok('We are already a slave of the new master') if ($old_peer eq $new_peer);
     
    my ($old_peer_host, $old_peer_port, $old_peer_user, $old_peer_password) = _get_connection_info($old_peer);
    _exit_error("No connection info for new peer '$old_peer'") unless defined($old_peer_host);
     
    my $old_peer_dbh = _mysql_connect($old_peer_host, $old_peer_port, $old_peer_user, $old_peer_password);
    if ($old_peer_dbh) {
        my $old_master_status = $old_peer_dbh->selectrow_hashref('SHOW MASTER STATUS');
        if (defined($old_master_status)) {
            $wait_log = $old_master_status->{File};
            $wait_pos = $old_master_status->{Position};
        }
        $old_peer_dbh->disconnect;
    }
 
    # Sync with logs
    my $res = $this_dbh->do("SELECT MASTER_POS_WAIT('$wait_log', $wait_pos)");
    _exit_error('SQL Query Error: ' . $this_dbh->errstr) unless($res);
 
    # Stop slave
    $res = $this_dbh->do('STOP SLAVE');
    _exit_error('SQL Query Error: ' . $this_dbh->errstr) unless($res);
     
    # Connect to new peer
    my $new_peer_dbh = _mysql_connect($new_peer_host, $new_peer_port, $new_peer_user, $new_peer_password);
    _exit_error("Can't connect to MySQL (host = $new_peer_host:$new_peer_port, user = $new_peer_user)! " . $DBI::errstr) unless ($new_peer_dbh);
 
    # Get log position of new master
    my $new_master_status = $new_peer_dbh->selectrow_hashref('SHOW MASTER STATUS');
    _exit_error('SQL Query Error: ' . $new_peer_dbh->errstr) unless($new_master_status);
 
    my $master_log = $new_master_status->{File};
    my $master_pos = $new_master_status->{Position};
 
    $new_peer_dbh->disconnect;
 
    # Get replication credentials
    my ($repl_user, $repl_password) = _get_replication_credentials($new_peer);
 
    # Change master
    my $sql = 'CHANGE MASTER TO'
              . " MASTER_HOST='$new_peer_host',"
              . " MASTER_PORT=$new_peer_port,"
              . " MASTER_USER='$repl_user',"
              . " MASTER_PASSWORD='$repl_password',"
              . " MASTER_LOG_FILE='$master_log',"
              . " MASTER_LOG_POS=$master_pos";
    $res = $this_dbh->do($sql);
    _exit_error('SQL Query Error: ' . $this_dbh->errstr) unless($res);
 
    # Start slave
    $res = $this_dbh->do('START SLAVE');
    _exit_error('SQL Query Error: ' . $this_dbh->errstr) unless($res);
 
    return 'OK';
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/35fe1cc1a633c3103ffc51f49febd832.html