⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmm_clone

📁 mysql+ha. 实现高可用性 http://code.google.com/p/mysql-master-master/
💻
字号:
#!/usr/bin/env perl# Use mandatory external modulesuse strict;use Cwd;use File::Basename;use Data::Dumper;use POSIX;use Config;use Getopt::Long;# Determine installation dir nameour $SELF_DIR = dirname(dirname(Cwd::abs_path(__FILE__)));# Include parts of the systemrequire $SELF_DIR . '/lib/config.pm';require $SELF_DIR . '/lib/log.pm';require $SELF_DIR . '/lib/db.pm';#-----------------------------------------------------------------#Parse optionsmy $config_file = "mmm_lvm.conf";my $host_name;my $clone_mode;my $copy_method;GetOptions("config=s" => \$config_file,           "host=s" => \$host_name,	       "clone-mode=s" => \$clone_mode,	       "copy-method=s" => \$copy_method);#-----------------------------------------------------------------# Read config fileour $config = ReadConfig($config_file);my $copy_method = $config->{default_copy_method} unless ($copy_method);my @clone_dirs : shared = split(/\,/, $config->{clone_dirs});$config->{clone_dirs} = \@clone_dirs;# Check host namemy $clone_host = $config->{host}->{$host_name};unless ($clone_host) {    print "Error: Invalid host name!\n\n";    PrintUsage();}# Check clone modeif ($clone_mode ne 'slave-slave' && $clone_mode ne 'master-slave' && $clone_mode ne 'master-master') {    print "Error: Unknown clone mode: $clone_mode\n\n";    PrintUsage();}# Check copy methodmy $method = $config->{copy_method}->{$copy_method};unless ($method) {    print "Error: Invalid copy method!\n\n";    PrintUsage();}LogNotice("Host: '$host_name'");LogNotice("Clone mode: '$clone_mode'");LogNotice("Copy method: '$copy_method'");LogNotice("Dirs to clone: '" . join(', ', @clone_dirs) . "'");#-----------------------------------------------------------------# Create config shortcutsmy $this = $config->{this};my $host = $config->{host}->{$this};my $my_cnf = $host->{my_cnf};if (!$my_cnf) {    LogWarn("Warning: No my.cnf file defined for $this host. Using default location...");    $my_cnf = "/etc/my.cnf" }LogNotice("-----------------------------------------------------------------");# Check local mysql process and shutdown it if it is runningmy $res = ShutdownLocalMysql();unless ($res =~ /^OK/) {    LogError("Can't stop local mysql daemon: $res");    exit(1);}LogNotice("-----------------------------------------------------------------");# Executing copying processmy $res = system("$SELF_DIR/sbin/mmm_get_dump --host $host_name --copy-method $copy_method");if ($res) {    LogError("Error: Can't copy data from remote server");    exit(1);}LogNotice("-----------------------------------------------------------------");#Loading status info from data dirmy $status = {};my $res = LoadStatusInfo(\$status);unless ($res =~ /^OK/) {    LogError("Error: Can't load status info from dumped data dir: $res");    exit(1);}LogDebug("Status: " . Dumper($status));LogNotice("-----------------------------------------------------------------");# Cleaning dump from master.info and binary logsmy $res = CleanupDump();unless ($res =~ /^OK/) {    LogError("Error: Can't cleanup dump from binaty logs: $res");    exit(1);}#-----------------------------------------------------------------my $master_info = {};$master_info->{'master_user'} = $config->{'replication_user'};$master_info->{'master_pass'} = $config->{'replication_password'};if ($clone_mode eq 'slave-slave') {    $master_info->{'master_host'} = $status->{slave}->{'Master_Host'};    $master_info->{'master_port'} = $status->{slave}->{'Master_Port'};    $master_info->{'master_log'} = $status->{slave}->{'Master_Log_File'};    $master_info->{'master_pos'} = $status->{slave}->{'Read_Master_Log_Pos'};}if ($clone_mode eq 'master-slave' || $clone_mode eq 'master-master') {    $master_info->{'master_host'} = $clone_host->{'mysql_host'};    $master_info->{'master_port'} = $clone_host->{'mysql_port'};    $master_info->{'master_log'} = $status->{master}->{'File'};    $master_info->{'master_pos'} = $status->{master}->{'Position'};}LogDebug("Master info: " . Dumper($master_info));#FIXME: need to update my_cnf to remove replication optionsLogNotice("-----------------------------------------------------------------");# Run local local mysql processmy $res = StartLocalMysql();unless ($res =~ /^OK/) {    LogError("Can't start local mysql daemon: $res");    exit(1);}LogNotice("-----------------------------------------------------------------");my $res = ChangeMasterTo($master_info);unless ($res =~ /^OK/) {    LogError("Error: Can't set master for local server: $res");    exit(1);}if ($clone_mode eq 'master-master') {    my $res = ChangePeerMasterTo();    unless ($res =~ /^OK/) {        LogError("Error: Can't set master for peer server: $res");        exit(1);    }}LogNotice("-----------------------------------------------------------------");LogNotice("Clone process done!\n\n\n");exit(0);#-----------------------------------------------------------------sub PrintUsage() {    print "Usage: $0 [--config <config file>] --host <host> --clone-mode <clone-mode> [--copy-method <copy_method>]\n";    print "Where:\n";    print "  Host = " . join('|', keys(%{$config->{host}})) . "\n";    print "  Clone mode: slave-slave|master-slave|master-master\n";    print "  Copy method = " . join('|', keys(%{$config->{copy_method}})) . " (default = $config->{default_copy_method})\n\n";    exit(1);}#-----------------------------------------------------------------sub ShutdownLocalMysql() {    my $pid_file = $host->{pid_file};        # Check pid file    if ($pid_file eq "") {        LogWarn("Warining: Can't find pid-file option in config file.");	    $pid_file = "/var/run/mysqld/mysqld.pid";    }        my $cnt;    my $pid;    if (-f $pid_file) {        # Read mysql pid        open(PID, $pid_file) || return "ERROR: Can't read mysql pid file ($pid_file)";        chomp($pid = <PID>);        close(PID);            # Check process        $cnt = kill(0, $pid);    }        if ($cnt == 0) {        LogWarn("MySql is not running now, skipping shutdown step...");        return  "OK: Mysql is not running";    }        LogNotice("MySql is running now. Going to stop it...");        #Stop mysql    my $rc_script = $host->{rc_script};    $rc_script = "/etc/init.d/mysql" if ($rc_script eq "");        my $res = system($rc_script, "stop");    if ($res) {        return "ERROR: Can't stop local MySql server!";    }    # Check process    my $wait = 15;    LogDebug("Waiting mysql process with $pid to shutdown: ");    while ($wait--) {        $cnt = kill(0, $pid);        last if ($cnt == 0);	LogDebug(".");	sleep(1);    }    if ($cnt != 0) {        PrintError("MySql Shutdown Failed!");	return "ERROR: MySql is running with PID $pid after shutdown request!";    }        LogDebug("Mysql Shutdown done: OK");    return "OK: MySql server is down now!";}#-----------------------------------------------------------------sub LoadStatusInfo($) {    my $status_info = shift;        LogDebug("Loading status info...");    unless ($config->{dest_dir} && -d $config->{dest_dir}) {        return "ERROR: Destination dir ($config->{dest_dir}) does not exists!";    }    my $status_file = $config->{dest_dir} . "/_mmm/status.txt";    unless (-f $status_file && -r $status_file) {        return "ERROR: Status file ($status_file) does not exists or is not readable!";    }        my $status_data = `cat $status_file`;    my $VAR1;    eval($status_data);    if ($@) {        return "ERROR: Can't parse status info: $@";    }        $$status_info = $VAR1;    return "OK!";}#-----------------------------------------------------------------sub StartLocalMysql() {    # Get pid file location    my $pid_file = $host->{pid_file};    # Check pid file    if ($pid_file eq "") {        LogWarn("Warining: Can't find pid-file option in config file.");	    $pid_file = "/var/run/mysqld/mysqld.pid";    }        if (-f $pid_file) {        # Read mysql pid        open(PID, $pid_file) || return "ERROR: Can't read mysql pid file ($pid_file)";        chomp(my $pid = <PID>);        close(PID);            # Check process        my $cnt = kill(0, $pid);	    if ($cnt) {	        return "ERROR: Local mysql is running now with pid = $pid!";	    }    }        LogNotice("MySql is not running now. Going to start it...");        # Start mysql    my $rc_script = $host->{rc_script};    $rc_script = "/etc/init.d/mysql" if ($rc_script eq "");        my $res = system($rc_script, "start");    if ($res) {        return "ERROR: Can't start local MySql server!";    }        return "OK: MySql server has been started!";}#-----------------------------------------------------------------sub CleanupDump() {    LogNotice("Cleaning dump from master.info and binary logs...");        my $master_log = $status->{master}->{File};    unless ($master_log =~ /^(.*)\.(\d+)$/) {        return "ERROR: Unknown master binary log file name format ($master_log)!";    }        LogDebug("Deleting master binary logs: $1.*");    system("find $config->{dest_dir} -name $1.* | xargs rm -vf");        if ($status->{slave} && $status->{slave}->{Relay_Log_File} ne '') {	    my $slave_log = $status->{slave}->{Relay_Log_File};	    unless ($slave_log =~ /^(.*)\.(\d+)$/) {	        return "ERROR: Unknown relay binary log file name format ($slave_log)!";	    }    }        LogDebug("Deleting relay binary logs: $1.*");    system("find $config->{dest_dir} -name $1.* | xargs rm -vf");        LogDebug("Deleting .info and .pid  files...");    system("find $config->{dest_dir} -name master.info | xargs rm -vf");    system("find $config->{dest_dir} -name relay-log.info | xargs rm -vf");    system("find $config->{dest_dir} -name *.pid | xargs rm -vf");        LogDebug("Changing permissions on mysql data dir...");    system("chown -R mysql:mysql $config->{dest_dir}");        return "OK";}#-----------------------------------------------------------------sub ChangeMasterTo($) {    my $master = shift;    LogNotice("Changing master info for local server...");    # get connection info    my $my_host = $host->{mysql_host};    my $my_port = $host->{mysql_port};    my $my_user = $host->{mysql_user};    my $my_pass = $host->{mysql_password};    my $dbh = MysqlConnect($my_host, $my_port, $my_user, $my_pass);    if (!$dbh) {        return "ERROR: Can't connect to local mysql (host = $my_host:$my_port, user = $my_user)!";    }    # Stop slave    my $res = ExecuteQuery($dbh, "STOP SLAVE");    return "ERROR: SQL Query Error: " . $dbh->errstr unless($res);    # Change master    my $sql = "CHANGE MASTER TO " .              "  MASTER_HOST='$master->{master_host}'," .              "  MASTER_PORT=$master->{master_port}," .              "  MASTER_USER='$master->{master_user}'," .              "  MASTER_PASSWORD='$master->{master_pass}'," .              "  MASTER_LOG_FILE='$master->{master_log}'," .              "  MASTER_LOG_POS=$master->{master_pos}";    my $res = ExecuteQuery($dbh, $sql);    return "ERROR: SQL Query Error: " . $dbh->errstr unless($res);        # Start slave    $res = ExecuteQuery($dbh, "START SLAVE");    return "ERROR: SQL Query Error: " . $dbh->errstr unless($res);    # disconnect    $dbh->disconnect;    return "OK";}#-----------------------------------------------------------------sub ChangePeerMasterTo() {    LogNotice("Changing master info for peer server...");    my $peer_host = $config->{host}->{$host_name};        # get connection info    my $my_host = $peer_host->{mysql_host};    my $my_port = $peer_host->{mysql_port};    my $my_user = $peer_host->{mysql_user};    my $my_pass = $peer_host->{mysql_password};    my $dbh = MysqlConnect($my_host, $my_port, $my_user, $my_pass);    if (!$dbh) {        return "ERROR: Can't connect to local mysql (host = $my_host:$my_port, user = $my_user)!";    }    # Stop slave    my $res = ExecuteQuery($dbh, "STOP SLAVE");    return "ERROR: SQL Query Error: " . $dbh->errstr unless($res);    # Change master    my $sql = "CHANGE MASTER TO " .              "  MASTER_HOST='$host->{mysql_host}'," .              "  MASTER_PORT=$host->{mysql_port}," .              "  MASTER_USER='$config->{replication_user}'," .              "  MASTER_PASSWORD='$config->{replication_password}'";	          my $res = ExecuteQuery($dbh, $sql);    return "ERROR: SQL Query Error: " . $dbh->errstr unless($res);        # Start slave    $res = ExecuteQuery($dbh, "START SLAVE");    return "ERROR: SQL Query Error: " . $dbh->errstr unless($res);    # disconnect    $dbh->disconnect;    return "OK";}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -