环境介绍:
主机名 IP MHA角色 MySQL角色
node1 192.168.56.26 Node MySQL Master
node2 192.168.56.27 Node MySQL Master behind
node3 192.168.56.28 Node MySQL slave
node4 192.168.56.36 Manager None

所有主机 /etc/hosts 添加信息
192.168.56.26 node1
192.168.56.27 node2
192.168.56.28 node3
192.168.56.36 node4

关闭selinux
永久生效:
/etc/selinux/config 文件修改如下参数
SELINUX=disabled

临时生效:
setenforce 0

关闭防火墙
chkconfig iptables off
chkconfig ip6tables off

/etc/init.d/iptables stop

安装MySQL:

解压软件
mkdir /opt/mysql
mv mysql-5.6.34-linux-glibc2.5-x86_64.tar.gz /opt/mysql
cd /opt/mysql
tar -zxvf mysql-5.6.34-linux-glibc2.5-x86_64.tar.gz

创建软连接
ln -s /opt/mysql/mysql-5.6.34-linux-glibc2.5-x86_64 /usr/local/mysql

创建运行用户
groupadd mysql
useradd -g mysql -d /usr/local/mysql -s /sbin/nologin -M -n mysql

创建所需的目录
mkdir -p /data/mysql/3307/{data,logs,tmp}
chown -R mysql:mysql /data/mysql/3307/
chown -R mysql:mysql /usr/local/mysql

配置文件内容
#my.cnf
[client]
port = 3307
socket = /data/mysql/3307/tmp/3307.sock

[mysql]
#pager="less -i -n -S"
#tee=/opt/mysql/query.log
no-auto-rehash

[mysqld]
#misc
user = mysql
basedir = /usr/local/mysql
datadir = /data/mysql/3307/data
port = 3307
socket = /data/mysql/3307/tmp/3307.sock
event_scheduler = 0

tmpdir = /data/mysql/3307/tmp
#timeout
interactive_timeout = 300
wait_timeout = 300

#character set
character-set-server = utf8

open_files_limit = 65535
max_connections = 100
max_connect_errors = 100000
lower_case_table_names =1

#symi replication

#rpl_semi_sync_master_enabled=1
#rpl_semi_sync_master_timeout=1000 # 1 second
#rpl_semi_sync_slave_enabled=1

#logs
log-output=file
slow_query_log = 1
slow_query_log_file = slow.log
log-error = error.log
log_warnings = 2
pid-file = mysql.pid
long_query_time = 1
#log-slow-admin-statements = 1
#log-queries-not-using-indexes = 1
log-slow-slave-statements = 1

#binlog
#binlog_format = STATEMENT
binlog_format = row
server-id = 330728
log-bin = /data/mysql/3307/logs/mysql-bin
binlog_cache_size = 4M
max_binlog_size = 256M
max_binlog_cache_size = 1M
sync_binlog = 0
expire_logs_days = 10
#procedure
log_bin_trust_function_creators=1

#
#gtid-mode = on
#enforce-gtid-consistency=1

#relay log
skip_slave_start = 1
max_relay_log_size = 128M
relay_log_purge = 1
relay_log_recovery = 1
relay-log=relay-bin
relay-log-index=relay-bin.index
log_slave_updates
#slave-skip-errors=1032,1053,1062
#skip-grant-tables

#buffers & cache
table_open_cache = 2048
table_definition_cache = 2048
table_open_cache = 2048
max_heap_table_size = 96M
sort_buffer_size = 128K
join_buffer_size = 128K
thread_cache_size = 200
query_cache_size = 0
query_cache_type = 0
query_cache_limit = 256K
query_cache_min_res_unit = 512
thread_stack = 192K
tmp_table_size = 96M
key_buffer_size = 8M
read_buffer_size = 2M
read_rnd_buffer_size = 16M
bulk_insert_buffer_size = 32M

#myisam
myisam_sort_buffer_size = 128M
myisam_max_sort_file_size = 10G
myisam_repair_threads = 1

#innodb
innodb_buffer_pool_size = 100M
innodb_buffer_pool_instances = 1
innodb_data_file_path = ibdata1:100M:autoextend
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 8M
innodb_log_file_size = 100M
innodb_log_files_in_group = 3
innodb_max_dirty_pages_pct = 50
innodb_file_per_table = 1
innodb_rollback_on_timeout
innodb_status_file = 1
innodb_io_capacity = 100
transaction_isolation = READ-COMMITTED
innodb_flush_method = O_DIRECT

修改my3307.cnf权限
chown mysql:mysql /etc/my.cnf

初始化数据库
/usr/local/mysql/scripts/mysql_install_db --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/data/mysql/3307/data --user=mysql

设置环境变量
echo "export PATH=$PATH:/usr/local/mysql/bin">> /etc/profile
source /etc/profile

cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld

启动MySQL
/etc/init.d/mysqld start

账号处理
grant all privileges on *.* to 'root'@'%' identified by 'chengce243' with grant option;
delete from mysql.user where password ='';
flush privileges;

搭建从库
主库创建复制账号
create user 'repl'@'192.168.56.%' identified by 'chengce243';
grant replication slave on *.* to 'repl'@'192.168.56.%';
flush privileges;

两个从库分别执行如下语句
MASTER_LOG_FILE 和 MASTER_LOG_POS 值,从主库 show master status;查看

CHANGE MASTER TO MASTER_HOST='192.168.56.26',MASTER_USER='repl',MASTER_PASSWORD='chengce243',MASTER_PORT=3307,MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=1718;

两个从库分别开启复制
start slave;

主库上创建
create user 'mhauser'@'192.168.56.%' identified by 'chengce243';
grant all privileges on *.* to 'mhauser'@'192.168.56.%';
flush privileges;

分别配置root用户和mysql用户互信

生成互信文件,输入如下命令,一路回车就行
ssh-keygen

cd ~/.ssh

cat id_rsa.pub > authorized_keys
chmod 600 *
cd ~/
scp -r .ssh 192.168.56.27:~/
scp -r .ssh 192.168.56.28:~/
scp -r .ssh 192.168.56.36:~/

最后每个节点都要验证
ssh node1 date
ssh node2 date
ssh node3 date
ssh node4 date

每个节点都要安装相关依赖包
yum install -y perl-devel
yum install -y perl-CPAN
yum install -y perl-Time-HiRes
yum install -y perl-DBD-MySQL
yum install -y perl-Params-Validate

yum install -y perl-Config-Tiny
yum install -y perl-Log-Dispatch
yum install -y perl-Parallel-ForkManager

MHA master节点,即node4安装
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm

MHA node节点,即node1/node2/node3安装
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm

为MHA的相关配置信息的存放规划目录结构(四台服务器均要操作):
mkdir -p /masterha_work/{conf,manager_workdir,rmt_mysql_binlog_workdir,script_dir,log}

自定义规则:
conf,存放MHA的配置文件
log,存放于MHA有关的日志信息
script_dir,除了默认的存放脚本的位置外,另一个存放自定义的或者官方提供的脚本的位置
manager_workdir,Manager的工作目录
rmt_mysql_binlog_workdir,当发生切换的时候,MySQL的binlog的临时存放路径

修改配置目录权限:
chown -R mysql:mysql /masterha_work
[root@node4 conf]# cat /masterha_work/conf/mha_total.cnf
[server default]
manager_workdir=/masterha_work/manager_workdir
manager_log=/masterha_work/log/manager.log

master_binlog_dir=/data/mysql/3307/logs
user=mhauser
password=chengce243

#master_ip_failover_script=/usr/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=node1 --orig_master_ip=192.168.56.26 --orig_master_port=3307
master_ip_online_change_script=/usr/bin/master_ip_online_change

ping_interval=1

remote_workdir=/masterha_work/rmt_mysql_binlog_workdir

repl_user=repl
repl_password=chengce243
port=3307

report_script=/usr/bin/send_report

secondary_check_script=/usr/local/bin/masterha_secondary_check -s node2 -s node1 --user=mhame --master_host=node2 --master_ip=192.168.56.27 --master_port=3307
shutdown_script=""

ssh_user=root

[server1]
hostname=192.168.56.26
port=3307

[server2]
hostname=192.168.56.27
candidate_master=1
check_repl_delay=0
port=3307

[server3]
hostname=192.168.56.28
port=3307
no_master=1

测试SSH连通性:

[root@node4 ~]# masterha_check_ssh --conf=/masterha_work/conf/mha_total.cnf
Fri Oct 6 18:14:21 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Oct 6 18:14:21 2017 - [info] Reading application default configuration from /masterha_work/conf/mha_total.cnf..
Fri Oct 6 18:14:21 2017 - [info] Reading server configuration from /masterha_work/conf/mha_total.cnf..
Fri Oct 6 18:14:21 2017 - [info] Starting SSH connection tests..
Fri Oct 6 18:14:22 2017 - [debug]
Fri Oct 6 18:14:21 2017 - [debug] Connecting via SSH from root@192.168.56.26(192.168.56.26:22) to root@192.168.56.27(192.168.56.27:22)..
Fri Oct 6 18:14:21 2017 - [debug] ok.
Fri Oct 6 18:14:21 2017 - [debug] Connecting via SSH from root@192.168.56.26(192.168.56.26:22) to root@192.168.56.28(192.168.56.28:22)..
Fri Oct 6 18:14:22 2017 - [debug] ok.
Fri Oct 6 18:14:22 2017 - [debug]
Fri Oct 6 18:14:21 2017 - [debug] Connecting via SSH from root@192.168.56.27(192.168.56.27:22) to root@192.168.56.26(192.168.56.26:22)..
Fri Oct 6 18:14:22 2017 - [debug] ok.
Fri Oct 6 18:14:22 2017 - [debug] Connecting via SSH from root@192.168.56.27(192.168.56.27:22) to root@192.168.56.28(192.168.56.28:22)..
Fri Oct 6 18:14:22 2017 - [debug] ok.
Fri Oct 6 18:14:23 2017 - [debug]
Fri Oct 6 18:14:22 2017 - [debug] Connecting via SSH from root@192.168.56.28(192.168.56.28:22) to root@192.168.56.26(192.168.56.26:22)..
Fri Oct 6 18:14:22 2017 - [debug] ok.
Fri Oct 6 18:14:22 2017 - [debug] Connecting via SSH from root@192.168.56.28(192.168.56.28:22) to root@192.168.56.27(192.168.56.27:22)..
Fri Oct 6 18:14:23 2017 - [debug] ok.
Fri Oct 6 18:14:23 2017 - [info] All SSH connection tests passed successfully.

测试MySQL复制的情况:
[root@node4 ~]# masterha_check_repl --conf=/masterha_work/conf/mha_total.cnf
Fri Oct 6 18:16:53 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Oct 6 18:16:53 2017 - [info] Reading application default configuration from /masterha_work/conf/mha_total.cnf..
Fri Oct 6 18:16:53 2017 - [info] Reading server configuration from /masterha_work/conf/mha_total.cnf..
Fri Oct 6 18:16:53 2017 - [info] MHA::MasterMonitor version 0.56.
Fri Oct 6 18:16:53 2017 - [info] GTID failover mode = 0
Fri Oct 6 18:16:53 2017 - [info] Dead Servers:
Fri Oct 6 18:16:53 2017 - [info] Alive Servers:
Fri Oct 6 18:16:53 2017 - [info] 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 18:16:53 2017 - [info] 192.168.56.27(192.168.56.27:3307)
Fri Oct 6 18:16:53 2017 - [info] 192.168.56.28(192.168.56.28:3307)
Fri Oct 6 18:16:53 2017 - [info] Alive Slaves:
Fri Oct 6 18:16:53 2017 - [info] 192.168.56.27(192.168.56.27:3307) Version=5.6.34-log (oldest major version between slaves) log-bin:enabled
Fri Oct 6 18:16:53 2017 - [info] Replicating from 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 18:16:53 2017 - [info] Primary candidate for the new Master (candidate_master is set)
Fri Oct 6 18:16:53 2017 - [info] 192.168.56.28(192.168.56.28:3307) Version=5.6.34-log (oldest major version between slaves) log-bin:enabled
Fri Oct 6 18:16:53 2017 - [info] Replicating from 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 18:16:53 2017 - [info] Not candidate for the new Master (no_master is set)
Fri Oct 6 18:16:53 2017 - [info] Current Alive Master: 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 18:16:53 2017 - [info] Checking slave configurations..
Fri Oct 6 18:16:53 2017 - [info] read_only=1 is not set on slave 192.168.56.27(192.168.56.27:3307).
Fri Oct 6 18:16:53 2017 - [warning] relay_log_purge=0 is not set on slave 192.168.56.27(192.168.56.27:3307).
Fri Oct 6 18:16:53 2017 - [info] read_only=1 is not set on slave 192.168.56.28(192.168.56.28:3307).
Fri Oct 6 18:16:53 2017 - [warning] relay_log_purge=0 is not set on slave 192.168.56.28(192.168.56.28:3307).
Fri Oct 6 18:16:53 2017 - [info] Checking replication filtering settings..
Fri Oct 6 18:16:53 2017 - [info] binlog_do_db= , binlog_ignore_db=
Fri Oct 6 18:16:53 2017 - [info] Replication filtering check ok.
Fri Oct 6 18:16:53 2017 - [info] GTID (with auto-pos) is not supported
Fri Oct 6 18:16:53 2017 - [info] Starting SSH connection tests..
Fri Oct 6 18:16:56 2017 - [info] All SSH connection tests passed successfully.
Fri Oct 6 18:16:56 2017 - [info] Checking MHA Node version..
Fri Oct 6 18:16:56 2017 - [info] Version check ok.
Fri Oct 6 18:16:56 2017 - [info] Checking SSH publickey authentication settings on the current master..
Fri Oct 6 18:16:56 2017 - [info] HealthCheck: SSH to 192.168.56.26 is reachable.
Fri Oct 6 18:16:57 2017 - [info] Master MHA Node version is 0.56.
Fri Oct 6 18:16:57 2017 - [info] Checking recovery script configurations on 192.168.56.26(192.168.56.26:3307)..
Fri Oct 6 18:16:57 2017 - [info] Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/data/mysql/3307/logs --output_file=/masterha_work/rmt_mysql_binlog_workdir/save_binary_logs_test --manager_version=0.56 --start_file=mysql-bin.000003
Fri Oct 6 18:16:57 2017 - [info] Connecting to root@192.168.56.26(192.168.56.26:22)..
Creating /masterha_work/rmt_mysql_binlog_workdir if not exists.. ok.
Checking output directory is accessible or not..
ok.
Binlog found at /data/mysql/3307/logs, up to mysql-bin.000003
Fri Oct 6 18:16:57 2017 - [info] Binlog setting check done.
Fri Oct 6 18:16:57 2017 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Fri Oct 6 18:16:57 2017 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=192.168.56.27 --slave_ip=192.168.56.27 --slave_port=3307 --workdir=/masterha_work/rmt_mysql_binlog_workdir --target_version=5.6.34-log --manager_version=0.56 --relay_log_info=/data/mysql/3307/data/relay-log.info --relay_dir=/data/mysql/3307/data/ --slave_pass=xxx
Fri Oct 6 18:16:57 2017 - [info] Connecting to root@192.168.56.27(192.168.56.27:22)..
Checking slave recovery environment settings..
Opening /data/mysql/3307/data/relay-log.info ... ok.
Relay log found at /data/mysql/3307/data, up to relay-bin.000002
Temporary relay log file is /data/mysql/3307/data/relay-bin.000002
Testing mysql connection and privileges..Warning: Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri Oct 6 18:16:58 2017 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=192.168.56.28 --slave_ip=192.168.56.28 --slave_port=3307 --workdir=/masterha_work/rmt_mysql_binlog_workdir --target_version=5.6.34-log --manager_version=0.56 --relay_log_info=/data/mysql/3307/data/relay-log.info --relay_dir=/data/mysql/3307/data/ --slave_pass=xxx
Fri Oct 6 18:16:58 2017 - [info] Connecting to root@192.168.56.28(192.168.56.28:22)..
Checking slave recovery environment settings..
Opening /data/mysql/3307/data/relay-log.info ... ok.
Relay log found at /data/mysql/3307/data, up to relay-bin.000002
Temporary relay log file is /data/mysql/3307/data/relay-bin.000002
Testing mysql connection and privileges..Warning: Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri Oct 6 18:16:58 2017 - [info] Slaves settings check done.
Fri Oct 6 18:16:58 2017 - [info]
192.168.56.26(192.168.56.26:3307) (current master)
+--192.168.56.27(192.168.56.27:3307)
+--192.168.56.28(192.168.56.28:3307)

Fri Oct 6 18:16:58 2017 - [info] Checking replication health on 192.168.56.27..
Fri Oct 6 18:16:58 2017 - [info] ok.
Fri Oct 6 18:16:58 2017 - [info] Checking replication health on 192.168.56.28..
Fri Oct 6 18:16:58 2017 - [info] ok.
Fri Oct 6 18:16:58 2017 - [warning] master_ip_failover_script is not defined.
Fri Oct 6 18:16:58 2017 - [warning] shutdown_script is not defined.
Fri Oct 6 18:16:58 2017 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.

配置VIP

str_vip="192.168.56.206"
str_mask="255.255.255.0"
str_nic_name="eth0:0"

ifconfig $str_nic_name $str_vip netmask $str_mask up
ifconfig $str_nic_name $str_vip netmask $str_mask down

master_ip_failover脚本修改

注释掉 FIXME,

原:
## Creating an app user on the new master
print "Creating app user on the new master..\n";
FIXME_xxx_create_user( $new_master_handler->{dbh} );
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();
## Update master ip on the catalog database, etc
FIXME_xxx;

修改如下:

## Creating an app user on the new master
print "Creating app user on the new master..\n";
#FIXME_xxx_create_user( $new_master_handler->{dbh} );
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();
## Update master ip on the catalog database, etc
#FIXME_xxx;

在 FIXME_xxx 后面增加对do_vip_crontab.sh 脚本的调用:

`/usr/bin/ssh -t root\@${orig_master_ip} "sh /data/script/do_vip_crontab.sh 1 0"`;
`/usr/bin/ssh -t root\@${new_master_ip} "sh /data/script/do_vip_crontab.sh 0 1"`;
`sh /script/shell/do_mha.sh > /work_dir/mha_manager/test_me/do_mha.log`;

注意,一定要用【;】结尾,否则脚本执行会出错。

修改 new_master_handler 中 mhamhauser用户与密码 :

# args: hostname, port, user, password, raise_error_or_not
#$new_master_handler->connect( $new_master_ip, $new_master_port,
# $new_master_user, $new_master_password, 1 );
$new_master_handler->connect( $new_master_ip, $new_master_port,
'mhauser', 'chengce243', 1 );

修改后 master_ip_failover 脚本如下:

[root@node4 ~]# cat /usr/bin/master_ip_failover
#!/usr/bin/env perl

# Copyright (C) 2011 DeNA Co.,Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

## Note: This is a sample script and is not complete. Modify the script based on your environment.

use strict;
use warnings FATAL => 'all';

use Getopt::Long;
use MHA::DBHelper;

my (
$command, $ssh_user, $orig_master_host,
$orig_master_ip, $orig_master_port, $new_master_host,
$new_master_ip, $new_master_port, $new_master_user,
$new_master_password
);
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
'new_master_user=s' => \$new_master_user,
'new_master_password=s' => \$new_master_password,
);

exit &main();

sub main {
if ( $command eq "stop" || $command eq "stopssh" ) {

# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {

# updating global catalog, etc
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {

# all arguments are passed.
# If you manage master ip address at global catalog database,
# activate new_master_ip here.
# You can also grant write access (create user, set read_only=0, etc) here.
my $exit_code = 10;
eval {
my $new_master_handler = new MHA::DBHelper();

# args: hostname, port, user, password, raise_error_or_not
$new_master_handler->connect( $new_master_ip, $new_master_port,
"mhauser", "chengce243", 1 );

## Set read_only=0 on the new master
$new_master_handler->disable_log_bin_local();
print "Set read_only=0 on the new master.\n";
$new_master_handler->disable_read_only();

## Creating an app user on the new master
print "Creating app user on the new master..\n";
#FIXME_xxx_create_user( $new_master_handler->{dbh} );
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();

## Update master ip on the catalog database, etc
#FIXME_xxx;

`echo "script begin running..." > /masterha_work/manager_workdir/master_ip_failover_run_shell`;

#`/usr/bin/ssh -t root\@${orig_master_ip} "service keepalived stop" > /work_dir/mha_manager/test_me/orig_master.log`;
#`/usr/bin/ssh -t root\@${new_master_ip} "service keepalived start" > /work_dir/mha_manager/test_me/new_master.log`;
`/usr/bin/ssh -t root\@${orig_master_ip} "sh /data/script/do_vip_crontab.sh 1 0"`;
`/usr/bin/ssh -t root\@${new_master_ip} "sh /data/script/do_vip_crontab.sh 0 1"`;
`sh /script/shell/do_mha.sh > /work_dir/mha_manager/test_me/do_mha.log`;

$exit_code = 0;
};
if ($@) {
warn $@;

# If you want to continue failover, exit 10.
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {

# do nothing
exit 0;
}
else {
&usage();
exit 1;
}
}

sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}

最后修改脚本权限:
chmod 755 /usr/bin/master_ip_failover

master_ip_online_change 脚本修改:

注释 FIXME_xxx_drop_app_user
原来:
## Drop application user so that nobody can connect. Disabling per-session binlog beforehand
$orig_master_handler->disable_log_bin_local();
print current_time_us() . " Drpping app user on the orig master..\n";
FIXME_xxx_drop_app_user($orig_master_handler);

修改如下:
## Drop application user so that nobody can connect. Disabling per-session binlog beforehand
$orig_master_handler->disable_log_bin_local();
print current_time_us() . " Drpping app user on the orig master..\n";
#FIXME_xxx_drop_app_user($orig_master_handler);

注释 FIXME_xxx_create_app_user
原来:
## Creating an app user on the new master
print current_time_us() . " Creating app user on the new master..\n";
FIXME_xxx_create_app_user($new_master_handler);
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();

修改如下:
## Creating an app user on the new master
print current_time_us() . " Creating app user on the new master..\n";
#FIXME_xxx_create_app_user($new_master_handler);
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();

修改 mhauser 用户的位置:
位置一:
# args: hostname, port, user, password, raise_error(die_on_error)_or_not
$new_master_handler->connect( $new_master_ip, $new_master_port,
"mhauser", "chengce243", 1 );

位置二:
# args: hostname, port, user, password, raise_error_or_not
$new_master_handler->connect( $new_master_ip, $new_master_port,
"mhauser", "chengce243", 1 );

增加do_vip_crontab.sh 脚本的调用:
`/usr/bin/ssh -t root\@${orig_master_ip} "sh /data/script/do_vip_crontab.sh 1 0"`;
`/usr/bin/ssh -t root\@${new_master_ip} "sh /data/script/do_vip_crontab.sh 0 1"`;

/masterha_work/manager_workdir/master_ip_failover_run_shell

修改后的脚本如下:
[root@node4 ~]# cat /usr/bin/master_ip_online_change
#!/usr/bin/env perl

# Copyright (C) 2011 DeNA Co.,Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

## Note: This is a sample script and is not complete. Modify the script based on your environment.

use strict;
use warnings FATAL => 'all';

use Getopt::Long;
use MHA::DBHelper;
use MHA::NodeUtil;
use Time::HiRes qw( sleep gettimeofday tv_interval );
use Data::Dumper;

my $_tstart;
my $_running_interval = 0.1;
my (
$command, $orig_master_is_new_slave, $orig_master_host,
$orig_master_ip, $orig_master_port, $orig_master_user,
$orig_master_password, $orig_master_ssh_user, $new_master_host,
$new_master_ip, $new_master_port, $new_master_user,
$new_master_password, $new_master_ssh_user,
);
GetOptions(
'command=s' => \$command,
'orig_master_is_new_slave' => \$orig_master_is_new_slave,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'orig_master_user=s' => \$orig_master_user,
'orig_master_password=s' => \$orig_master_password,
'orig_master_ssh_user=s' => \$orig_master_ssh_user,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
'new_master_user=s' => \$new_master_user,
'new_master_password=s' => \$new_master_password,
'new_master_ssh_user=s' => \$new_master_ssh_user,
);

exit &main();

sub current_time_us {
my ( $sec, $microsec ) = gettimeofday();
my $curdate = localtime($sec);
return $curdate . " " . sprintf( "%06d", $microsec );
}

sub sleep_until {
my $elapsed = tv_interval($_tstart);
if ( $_running_interval > $elapsed ) {
sleep( $_running_interval - $elapsed );
}
}

sub get_threads_util {
my $dbh = shift;
my $my_connection_id = shift;
my $running_time_threshold = shift;
my $type = shift;
$running_time_threshold = 0 unless ($running_time_threshold);
$type = 0 unless ($type);
my @threads;

my $sth = $dbh->prepare("SHOW PROCESSLIST");
$sth->execute();

while ( my $ref = $sth->fetchrow_hashref() ) {
my $id = $ref->{Id};
my $user = $ref->{User};
my $host = $ref->{Host};
my $command = $ref->{Command};
my $state = $ref->{State};
my $query_time = $ref->{Time};
my $info = $ref->{Info};
$info =~ s/^\s*(.*?)\s*$/$1/ if defined($info);
next if ( $my_connection_id == $id );
next if ( defined($query_time) && $query_time < $running_time_threshold );
next if ( defined($command) && $command eq "Binlog Dump" );
next if ( defined($user) && $user eq "system user" );
next
if ( defined($command)
&& $command eq "Sleep"
&& defined($query_time)
&& $query_time >= 1 );

if ( $type >= 1 ) {
next if ( defined($command) && $command eq "Sleep" );
next if ( defined($command) && $command eq "Connect" );
}

if ( $type >= 2 ) {
next if ( defined($info) && $info =~ m/^select/i );
next if ( defined($info) && $info =~ m/^show/i );
}

push @threads, $ref;
}
return @threads;
}

sub main {
if ( $command eq "stop" ) {
## Gracefully killing connections on the current master
# 1. Set read_only= 1 on the new master
# 2. DROP USER so that no app user can establish new connections
# 3. Set read_only= 1 on the current master
# 4. Kill current queries
# * Any database access failure will result in script die.
my $exit_code = 1;
eval {
## Setting read_only=1 on the new master (to avoid accident)
my $new_master_handler = new MHA::DBHelper();

# args: hostname, port, user, password, raise_error(die_on_error)_or_not
$new_master_handler->connect( $new_master_ip, $new_master_port,
"mhauser", "chengce243", 1 );
print current_time_us() . " Set read_only on the new master.. ";
$new_master_handler->enable_read_only();
if ( $new_master_handler->is_read_only() ) {
print "ok.\n";
}
else {
die "Failed!\n";
}
$new_master_handler->disconnect();

# Connecting to the orig master, die if any database error happens
my $orig_master_handler = new MHA::DBHelper();
$orig_master_handler->connect( $orig_master_ip, $orig_master_port,
$orig_master_user, $orig_master_password, 1 );

## Drop application user so that nobody can connect. Disabling per-session binlog beforehand
$orig_master_handler->disable_log_bin_local();
print current_time_us() . " Drpping app user on the orig master..\n";
#FIXME_xxx_drop_app_user($orig_master_handler);

## Waiting for N * 100 milliseconds so that current connections can exit
my $time_until_read_only = 15;
$_tstart = [gettimeofday];
my @threads = get_threads_util( $orig_master_handler->{dbh},
$orig_master_handler->{connection_id} );
while ( $time_until_read_only > 0 && $#threads >= 0 ) {
if ( $time_until_read_only % 5 == 0 ) {
printf
"%s Waiting all running %d threads are disconnected.. (max %d milliseconds)\n",
current_time_us(), $#threads + 1, $time_until_read_only * 100;
if ( $#threads < 5 ) {
print Data::Dumper->new( [$_] )->Indent(0)->Terse(1)->Dump . "\n"
foreach (@threads);
}
}
sleep_until();
$_tstart = [gettimeofday];
$time_until_read_only--;
@threads = get_threads_util( $orig_master_handler->{dbh},
$orig_master_handler->{connection_id} );
}

## Setting read_only=1 on the current master so that nobody(except SUPER) can write
print current_time_us() . " Set read_only=1 on the orig master.. ";
$orig_master_handler->enable_read_only();
if ( $orig_master_handler->is_read_only() ) {
print "ok.\n";
}
else {
die "Failed!\n";
}

## Waiting for M * 100 milliseconds so that current update queries can complete
my $time_until_kill_threads = 5;
@threads = get_threads_util( $orig_master_handler->{dbh},
$orig_master_handler->{connection_id} );
while ( $time_until_kill_threads > 0 && $#threads >= 0 ) {
if ( $time_until_kill_threads % 5 == 0 ) {
printf
"%s Waiting all running %d queries are disconnected.. (max %d milliseconds)\n",
current_time_us(), $#threads + 1, $time_until_kill_threads * 100;
if ( $#threads < 5 ) {
print Data::Dumper->new( [$_] )->Indent(0)->Terse(1)->Dump . "\n"
foreach (@threads);
}
}
sleep_until();
$_tstart = [gettimeofday];
$time_until_kill_threads--;
@threads = get_threads_util( $orig_master_handler->{dbh},
$orig_master_handler->{connection_id} );
}

## Terminating all threads
print current_time_us() . " Killing all application threads..\n";
$orig_master_handler->kill_threads(@threads) if ( $#threads >= 0 );
print current_time_us() . " done.\n";
$orig_master_handler->enable_log_bin_local();
$orig_master_handler->disconnect();

## After finishing the script, MHA executes FLUSH TABLES WITH READ LOCK
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
## Activating master ip on the new master
# 1. Create app user with write privileges
# 2. Moving backup script if needed
# 3. Register new master's ip to the catalog database

# We don't return error even though activating updatable accounts/ip failed so that we don't interrupt slaves' recovery.
# If exit code is 0 or 10, MHA does not abort
my $exit_code = 10;
eval {
my $new_master_handler = new MHA::DBHelper();

# args: hostname, port, user, password, raise_error_or_not
$new_master_handler->connect( $new_master_ip, $new_master_port,
"mhauser", "chengce243", 1 );

## Set read_only=0 on the new master
$new_master_handler->disable_log_bin_local();
print current_time_us() . " Set read_only=0 on the new master.\n";
$new_master_handler->disable_read_only();

## Creating an app user on the new master
print current_time_us() . " Creating app user on the new master..\n";
#FIXME_xxx_create_app_user($new_master_handler);
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();

## Update master ip on the catalog database, etc
#`/usr/bin/ssh -t root\@${orig_master_ip} "service keepalived stop"`;
#`/usr/bin/ssh -t root\@${new_master_ip} "service keepalived start"`;
`/usr/bin/ssh -t root\@${orig_master_ip} "sh /data/script/do_vip_crontab.sh 1 0"`;
`/usr/bin/ssh -t root\@${new_master_ip} "sh /data/script/do_vip_crontab.sh 0 1"`;

$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {

# do nothing
exit 0;
}
else {
&usage();
exit 1;
}
}

sub usage {
print
"Usage: master_ip_online_change --command=start|stop|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
die;
}

修改文件的权限:
chmod 755 /usr/bin/master_ip_online_change

MHA配置文件中打开对FAILOVER脚本的引用

[root@node4 ~]# cat /masterha_work/conf/masterha_consumer.cnf
[server default]
user=root
password=chengce243

ssh_user=root

master_binlog_dir=/data/mysql/3307/logs
remote_workdir=/masterha_work/rmt_mysql_binlog_workdir

repl_user=repl
repl_password=chengce243

master_ip_failover_script=/usr/bin/master_ip_failover
master_ip_online_change_script=/usr/bin/master_ip_online_change

ping_interval=30

manager_log=/masterha_work/log/manager_consumer.log

[server1]
hostname=192.168.56.26
port=3307

[server2]
hostname=192.168.56.27
candidate_master=1
check_repl_delay=0
port=3307

[server3]
hostname=192.168.56.28
port=3307
no_master=1

测试一下:
[root@node4 ~]# masterha_check_repl --conf=/masterha_work/conf/masterha_consumer.cnf
Fri Oct 6 22:16:34 2017 - [info] Reading default configuration from /etc/masterha_default.cnf..
Fri Oct 6 22:16:34 2017 - [info] Reading application default configuration from /masterha_work/conf/masterha_consumer.cnf..
Fri Oct 6 22:16:34 2017 - [info] Reading server configuration from /masterha_work/conf/masterha_consumer.cnf..
Fri Oct 6 22:16:34 2017 - [info] MHA::MasterMonitor version 0.56.
Fri Oct 6 22:16:34 2017 - [info] GTID failover mode = 0
Fri Oct 6 22:16:34 2017 - [info] Dead Servers:
Fri Oct 6 22:16:34 2017 - [info] Alive Servers:
Fri Oct 6 22:16:34 2017 - [info] 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 22:16:34 2017 - [info] 192.168.56.27(192.168.56.27:3307)
Fri Oct 6 22:16:34 2017 - [info] 192.168.56.28(192.168.56.28:3307)
Fri Oct 6 22:16:34 2017 - [info] Alive Slaves:
Fri Oct 6 22:16:34 2017 - [info] 192.168.56.27(192.168.56.27:3307) Version=5.6.34-log (oldest major version between slaves) log-bin:enabled
Fri Oct 6 22:16:34 2017 - [info] Replicating from 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 22:16:34 2017 - [info] Primary candidate for the new Master (candidate_master is set)
Fri Oct 6 22:16:34 2017 - [info] 192.168.56.28(192.168.56.28:3307) Version=5.6.34-log (oldest major version between slaves) log-bin:enabled
Fri Oct 6 22:16:34 2017 - [info] Replicating from 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 22:16:34 2017 - [info] Not candidate for the new Master (no_master is set)
Fri Oct 6 22:16:34 2017 - [info] Current Alive Master: 192.168.56.26(192.168.56.26:3307)
Fri Oct 6 22:16:34 2017 - [info] Checking slave configurations..
Fri Oct 6 22:16:34 2017 - [info] read_only=1 is not set on slave 192.168.56.27(192.168.56.27:3307).
Fri Oct 6 22:16:34 2017 - [warning] relay_log_purge=0 is not set on slave 192.168.56.27(192.168.56.27:3307).
Fri Oct 6 22:16:34 2017 - [info] read_only=1 is not set on slave 192.168.56.28(192.168.56.28:3307).
Fri Oct 6 22:16:34 2017 - [warning] relay_log_purge=0 is not set on slave 192.168.56.28(192.168.56.28:3307).
Fri Oct 6 22:16:34 2017 - [info] Checking replication filtering settings..
Fri Oct 6 22:16:34 2017 - [info] binlog_do_db= , binlog_ignore_db=
Fri Oct 6 22:16:34 2017 - [info] Replication filtering check ok.
Fri Oct 6 22:16:34 2017 - [info] GTID (with auto-pos) is not supported
Fri Oct 6 22:16:34 2017 - [info] Starting SSH connection tests..
Fri Oct 6 22:16:36 2017 - [info] All SSH connection tests passed successfully.
Fri Oct 6 22:16:36 2017 - [info] Checking MHA Node version..
Fri Oct 6 22:16:37 2017 - [info] Version check ok.
Fri Oct 6 22:16:37 2017 - [info] Checking SSH publickey authentication settings on the current master..
Fri Oct 6 22:16:37 2017 - [info] HealthCheck: SSH to 192.168.56.26 is reachable.
Fri Oct 6 22:16:37 2017 - [info] Master MHA Node version is 0.56.
Fri Oct 6 22:16:37 2017 - [info] Checking recovery script configurations on 192.168.56.26(192.168.56.26:3307)..
Fri Oct 6 22:16:37 2017 - [info] Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/data/mysql/3307/logs --output_file=/masterha_work/rmt_mysql_binlog_workdir/save_binary_logs_test --manager_version=0.56 --start_file=mysql-bin.000003
Fri Oct 6 22:16:37 2017 - [info] Connecting to root@192.168.56.26(192.168.56.26:22)..
Creating /masterha_work/rmt_mysql_binlog_workdir if not exists.. ok.
Checking output directory is accessible or not..
ok.
Binlog found at /data/mysql/3307/logs, up to mysql-bin.000003
Fri Oct 6 22:16:37 2017 - [info] Binlog setting check done.
Fri Oct 6 22:16:37 2017 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Fri Oct 6 22:16:37 2017 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=192.168.56.27 --slave_ip=192.168.56.27 --slave_port=3307 --workdir=/masterha_work/rmt_mysql_binlog_workdir --target_version=5.6.34-log --manager_version=0.56 --relay_log_info=/data/mysql/3307/data/relay-log.info --relay_dir=/data/mysql/3307/data/ --slave_pass=xxx
Fri Oct 6 22:16:37 2017 - [info] Connecting to root@192.168.56.27(192.168.56.27:22)..
Checking slave recovery environment settings..
Opening /data/mysql/3307/data/relay-log.info ... ok.
Relay log found at /data/mysql/3307/data, up to relay-bin.000002
Temporary relay log file is /data/mysql/3307/data/relay-bin.000002
Testing mysql connection and privileges..Warning: Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri Oct 6 22:16:38 2017 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=192.168.56.28 --slave_ip=192.168.56.28 --slave_port=3307 --workdir=/masterha_work/rmt_mysql_binlog_workdir --target_version=5.6.34-log --manager_version=0.56 --relay_log_info=/data/mysql/3307/data/relay-log.info --relay_dir=/data/mysql/3307/data/ --slave_pass=xxx
Fri Oct 6 22:16:38 2017 - [info] Connecting to root@192.168.56.28(192.168.56.28:22)..
Checking slave recovery environment settings..
Opening /data/mysql/3307/data/relay-log.info ... ok.
Relay log found at /data/mysql/3307/data, up to relay-bin.000002
Temporary relay log file is /data/mysql/3307/data/relay-bin.000002
Testing mysql connection and privileges..Warning: Using a password on the command line interface can be insecure.
done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Fri Oct 6 22:16:38 2017 - [info] Slaves settings check done.
Fri Oct 6 22:16:38 2017 - [info]
192.168.56.26(192.168.56.26:3307) (current master)
+--192.168.56.27(192.168.56.27:3307)
+--192.168.56.28(192.168.56.28:3307)

Fri Oct 6 22:16:38 2017 - [info] Checking replication health on 192.168.56.27..
Fri Oct 6 22:16:38 2017 - [info] ok.
Fri Oct 6 22:16:38 2017 - [info] Checking replication health on 192.168.56.28..
Fri Oct 6 22:16:38 2017 - [info] ok.
Fri Oct 6 22:16:38 2017 - [info] Checking master_ip_failover_script status:
Fri Oct 6 22:16:38 2017 - [info] /usr/bin/master_ip_failover --command=status --ssh_user=root --orig_master_host=node1 --orig_master_ip=192.168.56.26 --orig_master_port=3307 --command=status --ssh_user=root --orig_master_host=192.168.56.26 --orig_master_ip=192.168.56.26 --orig_master_port=3307
Fri Oct 6 22:16:38 2017 - [info] OK.
Fri Oct 6 22:16:38 2017 - [warning] shutdown_script is not defined.
Fri Oct 6 22:16:38 2017 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.

启动 mha守护进程

nohup masterha_manager --conf=/masterha_work/conf/masterha_consumer.cnf --ignore_last_failover > /tmp/mha_manager.log 2>&1&

node1、node2 上部署 do_vip_and_crontab.sh 脚本

[root@node1 ~]# cat /data/script/do_vip_crontab.sh
# file: do_vip_and_crontab.sh

# 职能:
# --> 1. 启动或停止:虚拟IP
# --> 2. 启用或禁用:crontab策略

# variable

# ---> 信号量
# 对于所有信号而言:
# 0,启用
# 1,禁用

#是否启用:VIP
#sign_vip=0
sign_vip="$1"

# 是否启用:crontab
#sign_crontab=0
sign_crontab="$2"

# 对于VIP而言
str_vip="192.168.56.206"
str_mask="255.255.255.0"
str_nic_name="eth0:0"

# 对于CRONTAB而言

# for RHEL6
# 如果是root用户,就会在:/var/spool/cron/root
file_crontab_dir="/var/spool/cron"
file_crontab_conf="$file_crontab_dir/mysql"

str_crontab_command="/bin/bash -x /data/script/run_commander.sh /data/script/backup.sh /data/script/mysql_auto_manage_binlog.sh > /dbbackup_idc/xtrabackup/consumer06/log/mysqlbackup.log 2>&1"
str_crontab_date="10 02 * * *"

str_crontab_command_sed=`echo "$str_crontab_command" | sed 's/\//\\\//g'`
str_crontab_date_sed=`echo "$str_crontab_date" | sed 's/*/\\\*/g'`

str_crontab_full="$str_crontab_date $str_crontab_command"
str_crontab_full_sed="$str_crontab_date_sed $str_crontab_command_sed"

str_block_crontab_content=`cat $file_crontab_conf | grep -v '#'`

# disable

echo "Crontab content:"
echo "$str_block_crontab_content"
echo ""

echo "var: str_crontab_date --> $str_crontab_date"
echo "var: str_crontab_command --> $str_crontab_command"
echo "--------------------------------------------"
echo "var: str_crontab_full --> $str_crontab_full"

echo ""

echo "var: str_crontab_date_sed --> $str_crontab_date_sed"
echo "var: str_crontab_command_sed --> $str_crontab_command_sed"
echo "--------------------------------------------"
echo "var: str_crontab_full_sed --> $str_crontab_full_sed"

echo ""

# running

if [ $sign_vip -eq "0" ]
then
echo "------------"
echo "VIP:: enable."
ifconfig $str_nic_name $str_vip netmask $str_mask up
echo ""
else
echo "------------"
echo "VIP:: disable."
ifconfig $str_nic_name $str_vip netmask $str_mask down
echo ""
fi

if [ $sign_crontab -eq "0" ]
then
echo "------------"
echo "CRONTAB:: enable."

if [[ $str_block_crontab_content =~ "$str_crontab_full" ]]
then
echo "CRONTAB Policy is in [$file_crontab_conf]"

else
echo "CRONTAB Policy is not in [$file_crontab_conf]"
echo "Put it in, ..."
echo "$str_crontab_full" >> $file_crontab_conf
echo "Done."
fi

echo ""
else
echo "------------"
echo "CRONTAB:: disable."

if [[ $str_block_crontab_content =~"$str_crontab_full" ]]
then
echo "CRONTAB Policy is in [$file_crontab_conf]"
echo "change it, ..."
sed -i "s/$str_crontab_full_sed/#$str_crontab_full_sed/g" $file_crontab_conf
echo "Done."

else
echo "CRONTAB Policy is not in [$file_crontab_conf]"

fi

echo ""
fi

# Finished

在node4上部署 call_do_mha.sh 脚本

[root@node4 script_dir]# cat /masterha_work/script_dir/call_do_mha.sh
# name: call_do_mha.sh

#variables

str_mha_app=$1

while [ true ]
do
sh /masterha_work/script_dir/do_mha.sh $str_mha_app
sleep 5
done

在node4上部署 do_mha.sh 脚本

[root@node4 ~]# cat /masterha_work/script_dir/do_mha.sh
#!/bin/bash
# Script
# Name: do_mha.sh
# APP vendor: MHA
# Linux vendor: RHEL / CentOS

# Author: leochen

# --------------------------
# variable and file path

# Part:: this script
str_mha_application=$1

# Part:: Linux
# Account info
str_linux_username="root"

# Part:: MySQL
# Account info
str_mysql_username="root"
str_mysql_password="chengce243"

str_repl_username="repl"
str_repl_password="chengce243"

# Part:: MHA
# pid
#str_pid_masterha_manager=`ps -ef | grep masterha_manager | grep perl | awk '{print $2}'`

str_pid_masterha_manager=`ps -ef | grep masterha_manager | grep "$str_mha_application" | grep perl | awk '{print $2}'`

# file
file_conf_mha_application="/masterha_work/conf/$str_mha_application.cnf"

# file: relation / by computed
file_log_mha_manager=`cat $file_conf_mha_application | grep --color manager_log | cut -d'=' -f2`

# variable: ip info
# 如果MHA中MySQL主库的候选服务器数量超过了两台,也许下面这个list参数,就会排上用场
list_ip_candicate=`cat $file_conf_mha_application | grep -B 2 "^candidate" | grep "hostname" | cut -d'=' -f2`

str_ip_orig_master=`cat $file_log_mha_manager | grep --color "MySQL Master failover" | cut -d'(' -f2 | cut -d':' -f1 | tail -n 1`
str_ip_new_master=`cat $file_log_mha_manager | grep --color "MySQL Master failover" | cut -d'(' -f3 | cut -d':' -f1 | tail -n 1`

str_ip_mha_manager="10.158.1.94"

# 为[change master]准备的参数
str_log_file_new_master=""
str_log_pos_new_master=""

# Part:: String SQL
str_sql_mysql_change_master=""

# --------------------------
# function

function do_sql() {
# variable
func_str_ip="$1"
func_str_sql="$2"

# action
# 本场景中不涉及到对MySQL某个库的操作,所以没有选择[db]
# mysql -u $user -p"$password" $db -N -e "$f_sql_str"
mysql -u $str_mysql_username -h $func_str_ip -p"$str_mysql_password" -N -e "$func_str_sql" -P3307
}

# 获取主库状态信息
#function get_info_mysql_master_new_master() {
# version ONE
#str_log_file_new_master=`do_sql "$str_ip_new_master" "show master status" | awk '{print $1}'`
#str_log_pos_new_master=`do_sql "$str_ip_new_master" "show master status" | awk '{print $2}'`

#}

# 生成orig_master作为slave加入new_master的[change master]SQL命令
function gen_sql_mysql_change_master() {
#if [[ "$str_log_file_new_master" == "" || $str_log_pos_new_master == "" ]]
#then
# get_info_mysql_master_new_master
#fi
#str_sql_mysql_change_master="CHANGE MASTER TO MASTER_HOST='$str_ip_new_master',MASTER_USER='$str_repl_username',MASTER_PASSWORD='$str_repl_password',MASTER_LOG_FILE='$str_log_file_new_master',MASTER_LOG_POS=$str_log_pos_new_master;"

# version TWO
func_temp_master_host_sed=`cat $file_log_mha_manager | grep --color "All other slaves should start" | tail -n 1 | cut -d',' -f1 | cut -d'=' -f2 | cut -d\' -f2`
func_temp_repl_password_sed=`cat $file_log_mha_manager | grep --color "All other slaves should start" | tail -n 1 | rev | cut -d\' -f2`

echo "======================"
echo "@@ func variable: func_temp_repl_password_sed = $func_temp_repl_password_sed"
echo "======================"
str_sql_mysql_change_master=`cat $file_log_mha_manager | grep --color "All other slaves should start" | tail -n 1 | sed "s#${func_temp_repl_password_sed}#${str_repl_password}#g" | cut -d':' -f4`
str_sql_mysql_change_master=`echo $str_sql_mysql_change_master | sed "s#${func_temp_master_host_sed}#${str_ip_new_master}#g"`
}

# 对指定主机执行Linux命令
# 前提:
# 1. IP可达
# 2. SSH等价关系
function do_linux_by_ssh() {
# variable
func_str_ip="$1"
func_str_user="$2"
func_str_command="$3"

# action
# ssh -t $func_str_user@$func_str_ip "$func_str_command"
ssh -t -t $func_str_user@$func_str_ip "$func_str_command"
}

# 处理VIP的事宜
function do_part_vip() {
do_linux_by_ssh "$str_ip_new_master" "root" "service keepalived start"
do_linux_by_ssh "$str_ip_orig_master" "root" "service keepalived stop"
}

function do_part_orig_master_is_new_slave() {
do_linux_by_ssh "$str_ip_orig_master" "root" "service mysqld start"
do_sql "$str_ip_orig_master" "set global read_only=1;"
do_sql "$str_ip_orig_master" "$str_sql_mysql_change_master"
do_sql "$str_ip_orig_master" "start slave;"
}

function do_part_mha_master_manager_start() {
do_linux_by_ssh "$str_ip_mha_manager" "root" "nohup masterha_manager --conf=$file_conf_mha_application --ignore_last_failover &"
}

# 如果PID不存在,则执行该脚本,否则,退出
function runable_by_mha_manager_pid() {
echo "-----------------"
echo "Script for MySQL Master HA"
echo "-----------------"
echo "Begin:: "`date "+|%Y-%m-%d|%H:%M:%S|"`

if [[ "$str_pid_masterha_manager" == "" ]]
then
echo "## masterha_manager is [NOT ALIVED]."
else
echo "## masterha_manager is [ALIVED]."
echo "[masterha_manager] PID is:: $str_pid_masterha_manager"

# do something.
echo "## Exit Script"
exit 0
fi
}

# --------------------------
# action

# 如果PID不存在,则执行该脚本,否则,退出
echo "------------------"
echo "app: runable_by_mha_manager_pid"
runable_by_mha_manager_pid
echo ""

echo "------------------"
echo "app: gen_sql_mysql_change_master"
gen_sql_mysql_change_master
echo ""
#echo "------------------"
#echo "app: do_part_vip"
#do_part_vip
#echo ""

echo "------------------"
echo "app: do_part_orig_master_is_new_slave"
do_part_orig_master_is_new_slave
echo ""

echo "------------------"
echo "app: do_part_mha_master_manager_start"
#do_part_mha_master_manager_start
nohup masterha_manager --conf=$file_conf_mha_application --ignore_last_failover &
echo ""

# --------------------------
# Show time

# ---------
# version one
# ---------
#echo "new master is:: $str_ip_new_master"
#echo "Master log file is:: $str_log_file_new_master"
#echo "Master log POS is:: $str_log_pos_new_master"
#echo "orig master --> new master ## SQL: CHANGE MASTER ## is:: $str_sql_mysql_change_master"

# ---------
# version two
# ---------
echo "================="
echo "MySQL info:"

echo "## Account and Password"
echo "username @ $str_mysql_username"
echo "password @ $str_mysql_password"
echo "--- for REPLICATION ---"
echo "repl @ username ## $str_repl_username"
echo "repl @ password ## $str_repl_password"
echo "## Master Server info"
echo "log file @ Master ## $str_log_file_new_master"
echo "log pos @ Master ## $str_log_pos_new_master"
echo ""

echo "================="
echo "SQL statement:"
echo "[CHANGE MASTER] -->"
echo "$str_sql_mysql_change_master"
echo ""

echo "================="
echo "MasterHA info:"

echo "## File and Path"
echo "MHA Global config file @ $file_conf_mha_global"
echo "MHA Application config file @ $file_conf_mha_application"
echo "MHA Log file:: masterha_manager @ $file_log_mha_manager"

echo "## Architecture"
echo "Candicate Server list::"
echo "$list_ip_candicate"

echo "## IP"
echo "MHA Manager Server:: $str_ip_mha_manager"
echo "Last:: new master:: $str_ip_new_master"
echo "Last:: orig master:: $str_ip_orig_master"
echo ""

# --------------------------
echo "-----------------"
echo "Finished:: "`date "+|%Y-%m-%d|%H:%M:%S|"`
# Done

启动 call_do_mha.sh 脚本

nohup sh /masterha_work/script_dir/call_do_mha.sh masterha_consumer &

MHA 一主两从搭建-脚本VIP-自动切换的更多相关文章

  1. MHA 一主两从搭建-keepalived-手动切换

    环境介绍:主机名 IP MHA角色 MySQL角色node1 192.168.56.26 Node MySQL Master node2 192.168.56.27 Node MySQL Master ...

  2. redis一主两从搭建

    一主两从搭建: 主配: daemonize yes port 6379 logfile ./redis6379.log dir ./ bind 10.131.156.170 从1配: daemoniz ...

  3. 通过keepalived实现 MySQL VIP 自动切换

    首先配置keepalived.链接如下:http://blog.itpub.net/28939273/viewspace-1808369/ 主服务器keepalived的配置文件内容如下: [root ...

  4. 阿里云ECS服务器上搭建keepalived+mha+mysql5.6+gtid+一主两从+脚本判断架构踩的坑

    最近,公司项目搭建了一套后端数据库架构,不是在RDS,是在阿里云的ECS服务器上搭建keepalived.mha.mysql5.6.gtid.一主两从架构,目前还没有实现读写分离,以后架构升级,可能代 ...

  5. redis(一主两从三哨兵模式搭建)记录

    转自:http://www.cnblogs.com/fly-piglet/p/9836314.html 目的: 让看看这篇文章的的人能够知道:软件架构.软件的安装.配置.基本运维的操作.高可用测试.也 ...

  6. 【运维技术】redis(一主两从三哨兵模式搭建)记录

    redis(一主两从三哨兵模式搭建)记录 目的: 让看看这篇文章的的人能够知道:软件架构.软件的安装.配置.基本运维的操作.高可用测试.也包含我自己,能够节省对应的时间. 软件架构: 生产环境使用三台 ...

  7. Redis集群主从复制(一主两从)搭建配置教程【Windows环境】

    如何学会在合适的场景使用合适的技术方案,这值得思考. 由于本地环境的使用,所以搭建一个本地的Redis集群,本篇讲解Redis主从复制集群的搭建,使用的平台是Windows,搭建的思路和Linux上基 ...

  8. Docker搭建Redis一主两从三哨兵

    作者:oscarwin juejin.im/post/5d26b03de51d454fa33b1960 这次实验准备了三台云主机,系统为Debian,ip分别为:35.236.172.131 ,35. ...

  9. 实践 - 搭建Redis一主两从三哨兵

    实践 - 搭建Redis一主两从三哨兵 原因: 最近在复习Redis的时候,学习到了为了提高Redis集群的高可用性,有一个模式为哨兵模式.哨兵模式的作用是为了在主节点出现阻塞或者错误,无法接收数据的 ...

随机推荐

  1. 【Pycharm】【HTML】注释问题

    学习HTML中,遇到的注释前存在空行的问题: 只要找到Pycharm设置中:勾选去掉即可

  2. PLSQL乱码&TNS-12557: protocol adapter not loadable解决

    PLSQL乱码&TNS-12557: protocol adapter not loadable解决 PLSQL乱码&TNS-12557: protocol adapter not l ...

  3. opera mini 改服

    opera mini 改服 下载 opera 和 opera mini ftp://ftp.opera.com/pub/opera/android/mini/ ftp://ftp.opera.com/ ...

  4. android图片特效处理之光照效果

    这篇将讲到图片特效处理的光照效果.跟前面一样是对像素点进行处理,算法是通用的. 算法原理:图片上面的像素点按照给定圆心,按照圆半径的变化,像素点的RGB值分别加上相应的值作为当前点的RGB值. 例: ...

  5. sql server向表里添加字段

    ADD mcTypeE VARCHAR(20) NULL,mcGoodsE VARCHAR(20) NULL, mcTypeF VARCHAR(20) NULL,mcGoodsF VARCHAR(20 ...

  6. WPF 入门《数据绑定》

    简单而言, 数据绑定是一种关系, 这种关系告诉WPF 从一个源目标对象中提取一些信息, 并且使用该信息设置为目标对象的属性.目标属性总是依赖项属性, 并且通常位于WPF元素中. 然而, 源对象可以是任 ...

  7. POJ 3045 Cow Acrobats (最大化最小值)

    题目链接:click here~~ [题目大意] 给你n头牛叠罗汉.每头都有自己的重量w和力量s,承受的风险数rank就是该牛上面全部牛的总重量减去该牛自身的力量,题目要求设计一个方案使得全部牛里面风 ...

  8. [Javascript] Classify text into categories with machine learning in Natural

    In this lesson, we will learn how to train a Naive Bayes classifier or a Logistic Regression classif ...

  9. Core Animation 文档翻译—附录A(Layer样貌相关属性动画)

    前言   在渲染过程中,核心动画获取Layer的各种属性并以特定的顺序渲染他们.这个顺序决定了Layer的最终的样貌.本节将会阐述通过设置不同的Layer样貌相关属性对应产生的渲染结果. 注意:Mac ...

  10. DataTable +chart控件

    //这是仿你的DataTable //-----开始--------- DataTable dataTable1 = new System.Data.DataTable(); dataTable1.C ...