sql server 执行代理作业脚本_从零开始部署MHA以及相关MHA原始脚本定制

近期公司要做mysql数据库的高可用,通过前期调研了主从+heartbeat,MHA,PXC三个类型的方案,也结合了当前公司的技术能力和业务情况,最终是选择了MHA来作为高可用的方案。 一、MHA简介 MHA作者Yoshinori Matsunobu

github

https://github.com/yoshinorim/mha4mysql-manager
Yoshinori Matsunobu是个大神 现在在Facebook,直接看官方的介绍:

ab287f9d937c14e507230442e4a4e8f4.png

这里就不过多描述了,大家感兴趣可以直接去作者Github的wiki查看。

二、MHA的Failover原理

这里直接引用 “兰春”的部分文章内容,在此感谢作者分享

MySQL Master High Available 源码篇

https://developer.aliyun.com/article/59233

2.1 非GTID复制模式Failover原理

132937a87a0d82fc18d32d79add7ae12.png
Phase 1: Configuration Check Phaseinit_config(): 初始化配置MHA::ServerManager::init_binlog_server: 初始化binlog servercheck_settings()  a. check_node_version(): 查看MHA的版本  b. connect_all_and_read_server_status(): 检测确认各个Node节点MySQL是否可以连接  c. get_dead_servers(),get_alive_servers(),get_alive_slaves():再次检测一次node节点的状态  d. print_dead_servers(): 是否挂掉的master是否是当前的master  e. MHA::DBHelper::check_connection_fast_util : 快速判断dead server,是否真的挂了,如果ping_type=insert,不会double check  f. MHA::NodeUtil::drop_file_if($_failover_error_file|$_failover_complete_file): 检测上次的failover文件  g. 如果上次failover的时间在8小时以内,那么这次就不会failover,除非配置了额外的参数  h. start_sql_threads_if(): 查看所有slave的Slave_SQL_Running是否为Yes,若不是则启动SQL thread  is_gtid_auto_pos_enabled(): 判断是否是GTID模式Phase 2: Dead Master Shutdown Phase..  force_shutdown($dead_master):  a. stop_io_thread(): stop所有slave的IO_thread  b. force_shutdown_internal($dead_master):      b_1. master_ip_failover_script: 如果有这个脚本,则执行里面的逻辑(比如:切换vip)      b_2. shutdown_script:如果有这个脚本,则执行里面的逻辑(比如:Power off 服务器)Phase 3: Master Recovery Phase..  Phase 3.1: Getting Latest Slaves Phase..  * check_set_latest_slaves()      a. read_slave_status(): 获取所有show slave status 信息      b. identify_latest_slaves(): 找到最新的slave是哪个      c. identify_oldest_slaves(): 找到最老的slave是哪个  Phase 3.2: Saving Dead Master's Binlog Phase..    * save_master_binlog($dead_master);      -> 如果dead master可以ssh,那么           b_1_1. save_master_binlog_internal: 用node节点save_binary_logs脚本拷贝相应binlog到manager               diff_binary_log 生产差异binlog日志           b_1_2. file_copy: 将差异binlog拷贝到manager节点的 manager_workdir目录下      -> 如果dead master不可以ssh           b_1_3. 那么差异日志就会丢失  Phase 3.3: Determining New Master Phase..  b. 如果GTID auto_pos没有打开,调用find_latest_base_slave()      b_1. find_latest_base_slave_internal: 寻找拥有所有relay-log的最新slave,如果没有,则failover失败              b_1_1. find_slave_with_all_relay_logs:                      b_1_1_1. apply_diff_relay_logs: 查看最新的slave是否有其他slave缺失的relay-log    c. select_new_master: 选举new master      c_1. MHA::ServerManager::select_new_master:         #If preferred node is specified, one of active preferred nodes will be new master.         #If the latest server behinds too much (i.e. stopping sql thread for online backups), we should not use it as a new master, but we should fetch relay log there         #Even though preferred master is configured, it does not become a master if it's far behind           get_candidate_masters(): 获取配置中候选节点         get_bad_candidate_masters(): 以下条件不能成为候选master             # dead server             # no_master >= 1             # log_bin=0             # oldest_major_version=0             # check_slave_delay: 检查是否延迟非常厉害(可以通过设置no_check_delay忽略)                 {Exec_Master_Log_Pos} + 100000000 只要binlog position不超过100000000 就行         选举流程:先看candidate_master,然后找 latest slave, 然后再随机挑选  Phase 3.3(3.4): New Master Diff Log Generation Phase..  * recover_master_internal           recover_relay_logs:                 判断new master是否为最新的slave,如果不是,则生产差异relay logs,并发送给新master           recover_master_internal:                 将之前生产的dead master上的binlog传送给new master  Phase 3.4: Master Log Apply Phase..  * apply_diff:         a. wait_until_relay_log_applied: 直到new master完成所有relay log,否则一直等待         b. 判断Exec_Master_Log_Pos == Read_Master_Log_Pos, 如果不等,那么生产差异日志:                     save_binary_logs --command=save         c. apply_diff_relay_logs --command=apply:对new master进行恢复                     c_1. exec_diff:Exec_Master_Log_Pos和Read_Master_Log_Pos的差异日志                     c_2. read_diff:new master与lastest slave的relay log的差异日志                     c_3. binlog_diff:lastest slave与daed master之间的binlog差异日志  * 如果设置了master_ip_failover_script脚本,那么会执行这里面的脚本(一般用来漂移vip)    * disable_read_only(): 允许new master可写Phase 4: Slaves Recovery Phase..  recover_slaves_internal    Phase 4.1: Starting Parallel Slave Diff Log Generation Phase..    recover_all_slaves_relay_logs: 生成Slave与New Slave之间的差异日志,并将该日志拷贝到各Slave的工作目录下  Phase 4.2: Starting Parallel Slave Log Apply Phase..    * recover_slave:        对每个slave进行恢复,跟以上Phase 3.4: Master Log Apply Phase中的 apply_diff一样    * change_master_and_start_slave:        重新指向到new master,并且start slavePhase 5: New master cleanup phase..  reset_slave_on_new_master  在new master上执行reset slave all;
2.2 非GTID复制模式Failover原理 04580cf455cd92af5d49223b3c9ea2f1.png
Phase 1: Configuration Check Phase  init_config(): 初始化配置  MHA::ServerManager::init_binlog_server: 初始化binlog server  check_settings()    a. check_node_version(): 查看MHA的版本    b. connect_all_and_read_server_status(): 检测确认各个Node节点MySQL是否可以连接    c. get_dead_servers(),get_alive_servers(),get_alive_slaves():再次检测一次node节点的状态    d. print_dead_servers(): 是否挂掉的master是否是当前的master    e. MHA::DBHelper::check_connection_fast_util : 快速判断dead server,是否真的挂了,如果ping_type=insert,不会double check    f. MHA::NodeUtil::drop_file_if($_failover_error_file|$_failover_complete_file): 检测上次的failover文件    g. 如果上次failover的时间在8小时以内,那么这次就不会failover,除非配置了额外的参数    h. start_sql_threads_if(): 查看所有slave的Slave_SQL_Running是否为Yes,若不是则启动SQL thread  is_gtid_auto_pos_enabled(): 判断是否是GTID模式Phase 2: Dead Master Shutdown Phase completed.  force_shutdown($dead_master):    a. stop_io_thread(): stop所有slave的IO_thread    b. force_shutdown_internal($dead_master):      b_1. master_ip_failover_script: 如果有这个脚本,则执行里面的逻辑(比如:切换vip)      b_2. shutdown_script:如果有这个脚本,则执行里面的逻辑(比如:Power off 服务器)Phase 3: Master Recovery Phase..  Phase 3.1: Getting Latest Slaves Phase..    * check_set_latest_slaves()        a. read_slave_status(): 获取所有show slave status 信息        b. identify_latest_slaves(): 找到最新的slave是哪个        c. identify_oldest_slaves(): 找到最老的slave是哪个  Phase 3.2: Saving Dead Master's Binlog Phase.. (GTID 模式下没有这一步)  Phase 3.3: Determining New Master Phase..    get_most_advanced_latest_slave(): 获取最新的slave    c. select_new_master: 选举new master      c_1. MHA::ServerManager::select_new_master:         #If preferred node is specified, one of active preferred nodes will be new master.         #If the latest server behinds too much (i.e. stopping sql thread for online backups), we should not use it as a new master, but we should fetch relay log there         #Even though preferred master is configured, it does not become a master if it's far behind           get_candidate_masters(): 获取配置中候选节点         get_bad_candidate_masters(): 以下条件不能成为候选master             # dead server             # no_master >= 1             # log_bin=0             # oldest_major_version=0             # check_slave_delay: 检查是否延迟非常厉害(可以通过设置no_check_delay忽略)                 {Exec_Master_Log_Pos} + 100000000 只要binlog position不超过100000000 就行         选举流程:先看candidate_master,然后找 latest slave, 然后再随机挑选    Phase 3.3: New Master Recovery Phase..    * recover_master_gtid_internal:        wait_until_relay_log_applied: 候选master等待所有relay-log都应用完        如果候选master不是最新的slave:            $latest_slave->wait_until_relay_log_applied($log): 最新的slave应用完所有的relay-log            change_master_and_start_slave :让候选master同步到latest master,追上latest slave            获取候选master此时此刻的日志信息,以便后面切换        如果候选master是最新的slave:            获取候选master此时此刻的日志信息,以便后面切换        save_from_binlog_server:            如果配置了binlog server,那么在binlogsever 能连的情况下,将binlog 拷贝到Manager,并生成差异日志diff_binlog(save_binary_logs --command=save)        apply_binlog_to_master:            Applying differential binlog:应用差异的binlog到new masterPhase 4: Slaves Recovery Phase..  Phase 4.1: Starting Slaves in parallel..    * recover_slaves_gtid_internal:        change_master_and_start_slave: 因为master已经恢复,那么slave直接change master auto_pos=1 的模式就可以恢复        gtid_wait:用此等待同步全部追上Phase 5: New master cleanup phase..  reset_slave_on_new_master  在new master上执行reset slave all;
三、MHA安装 3.1MHA安装包简介

MHA由perl编写,分为两部分组件

一个是MHA Node,里面的组件:    save_binary_logs                保存和复制master的二进制日志  apply_diff_relay_logs           识别差异的中继日志事件并将其差异的事件应用于其他的slave  filter_mysqlbinlog              去除不必要的ROLLBACK事件(MHA已不再使用这个工具)  purge_relay_logs                清除中继日志(不会阻塞SQL线程)一个是MHA Manager,里面包含很多组件:  masterha_check_ssh              检查MHA的SSH配置状况  masterha_check_repl             检查MySQL复制状况  masterha_manger                 启动MHA  masterha_check_status           检测当前MHA运行状态  masterha_master_monitor         检测master是否宕机  masterha_master_switch          控制故障转移(自动或者手动)  masterha_conf_host              添加或删除配置的server信息

MHA Node是要在每一个mysql复制组内的服务器上都要安装的,而MHA Manage可以安装在任意能和复制组通信的服务器上,当然也包括复制组内的某个机器。

3.2安装方式 RPM Or Source

RHEL/CentOS 使用rpm安装:

yum install perl-DBD-MySQLyum install perl-Config-Tinyyum install perl-Log-Dispatchyum install perl-Parallel-ForkManagerrpm -ivh mha4mysql-node-X.Y-0.noarch.rpmrpm -ivh mha4mysql-manager-X.Y-0.noarch.rpm

源码编译安装:

## Install DBD::mysql if not installed## Install dependent Perl modules# MHA Node (See above)# Config::Tiny## perl -MCPAN -e "install Config::Tiny"# Log::Dispatch## perl -MCPAN -e "install Log::Dispatch"# Parallel::ForkManager ## perl -MCPAN -e "install Parallel::ForkManager"## Installing MHA Node$ tar -zxf mha4mysql-node-X.Y.tar.gz$ perl Makefile.PL$ make$ sudo make install## Installing MHA Manager$ tar -zxf mha4mysql-manager-X.Y.tar.gz$ perl Makefile.PL$ make$ sudo make install
四、MHA脚本详解和定制开发4.1 脚本及配置简介 43d78e7d4efd27b6bc3671be993177b1.pngMHA配置分为三个等级: Local/App/Global,参数作用域越来越大,masterha_default.conf中为Global级别配置,app*.conf为App级配置,app*.conf中的[server*]为Local级别配置,先有个大体概念,下面详细讲解每个文件。 masterha_default.conf说明:

masterha_default.conf是MHA的全局配置文件,所有公共配置都可以写到这里面 比如机器的账户 失败检测的心跳时间 master_ip_failover_script的路径等等,也就是所有的MHA进程都会共用这里的配置。

[server default]#监控ping_interval=3 #心跳检测时间间隔#shutdown_script="" #发生失败切换执行的关机脚本report_script=/home/SendEmail.sh #失败切换后实现消息通知的脚本#切换调用的脚本master_ip_failover_script= /etc/masterha/master_ip_failovermaster_ip_online_change_script= /etc/masterha/master_ip_online_change
App1.conf说明:

App1.conf,看了都会疑问,为啥是App1.conf呢?因为一个mha可以管理多个复制组,每个复制组都有自己独立的app.conf文件,所以是app1,app2,app3等

[server default]manager_log=/var/log/masterha/app1/app1.log #MHa log 日志文件位置manager_workdir=/var/log/masterha/app1 #MHA的工作空间master_binlog_dir=/data/mysql/mysql3306/logs # master的mysqlbinlog的位置user=mysqluser  #mysql超级账户 为了切换过程中对mysql进行一些配置password=123456repl_password=123456 #mysql复制账户repl_user=repl_userssh_user=root #ssh的账户名[server1]check_repl_delay=0 #如果候选master有延迟的话,relay日志超过100m,failover切换不能成功,加上此参数后会忽略延迟日志大小。hostname=192.168.* #当前库的机器IPignore_fail=1 #如果这个节点挂了,mha将不可用,加上这个参数,slave挂了一样可以用[server2]check_repl_delay=0hostname=192.168.*ignore_fail=1[server3]check_repl_delay=0hostname=192.168.*ignore_fail=1[binlog1]hostname=192.168.* #binlog server服务器的ipmaster_binlog_dir=/data/mysql/mysql3306/logs/ #binlog文件所在的路径no_master=1  #从不将这台主机转换为master

这里重点说下这个[binlog1]节点,使用0.56之前的版本是没有这个参数的,这个是为了支持GTID的,具体可以参考mysql5.6基于GTID模式之高可用架构搭建-MHA(mha0.56),MHA failover GTID 专题等,这里说下,gtid的补偿日志机制跟非gtid是有所不同的,所以配置[binlog1]是必须的,我这里直接配置的主服务的ip并且binlog存放的物理目录直接指向了实际msater mysql的binlog文件所在的目录下了,即将master当做了binlog server,这种配置方式是可行的,但是一旦主库所在的服务器down机或者无法通过ssh连接了,差异日志是获取不到也就是无法补偿到新的master上的。

还有很多可配置的参数,具体可以参考作者Github的wiki:

MHA Parameters

https://github.com/yoshinorim/mha4mysql-manager/wiki/Parameters

master_ip_failover失败切换脚本:

MHA做高可用需要用到虚拟vip,以实现主库宕机后自动切换到新主上,而业务无感知,vip的管理方案有两种:一种是脚本管理vip,也就是mha推荐的;另一种是Keepalived,看了很多文章和根据实践,推荐使用脚本管理vip,避免发生脑裂。
#!/usr/bin/env perluse strict;use warnings FATAL => 'all';use Getopt::Long;my (    $command,          $ssh_user,        $orig_master_host, $orig_master_ip,    $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port);my $gateway = '192.168.11.1';   ---这个是网关地址my $vip = '192.168.11.251/24'; ---vip地址my $onlyvip = '192.168.11.251'; vipmy $key = '0'; ---网卡的别名编号my $eth = 'ens32'; --网卡名称my $ssh_start_vip = "/sbin/ifconfig $eth:$key $vip up;/sbin/arping -I $eth -c 3 -s $onlyvip $gateway";my $ssh_stop_vip = "/sbin/ifconfig $eth:$key down";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,);exit &main();sub main {    print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";    print "\n\nIN Master_ip_failover_command:====$command===\n\n";    if ( $command eq "stop" || $command eq "stopssh" ) {        my $exit_code = 1;        eval {            print "Disabling the VIP on old master: $orig_master_host \n";            &stop_vip();            $exit_code = 0;        };        if ($@) {            warn "Got Error: $@\n";            exit $exit_code;        }        exit $exit_code;    }    elsif ( $command eq "start" ) {        my $exit_code = 10;        eval {            print "Enabling the VIP - $vip on the new master - $new_master_host \n";            &start_vip();            $exit_code = 0;        };        if ($@) {            warn $@;            exit $exit_code;        }        exit $exit_code;    }    elsif ( $command eq "status" ) {        print "Checking the Status of the script.. OK \n";        exit 0;    }    else {        &usage();        exit 1;    }}sub start_vip() {    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;}sub stop_vip() {     return 0  unless  ($ssh_user);    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;}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";}

重点关注下这部分参数:

my $gateway = '192.168.11.1';   ---这个是网关地址my $vip = '192.168.11.251/24'; ---vip地址,带网络号my $onlyvip = '192.168.11.251'; vipmy $key = '0'; ---网卡的别名编号my $eth = 'ens32'; --网卡名称my $ssh_start_vip = "/sbin/ifconfig $eth:$key $vip up;/sbin/arping -I $eth -c 3 -s $onlyvip $gateway";my $ssh_stop_vip = "/sbin/ifconfig $eth:$key down";

gateway及eth : 这里网关和网卡名字不用说了, 直接用 ip addr就可以查询到本地网卡的名称是啥,直接看下网卡配置就知道网关地址是啥,vip这个就是在同一个网段。

onlyvip ,vip:192.168.11.251/24后面的24是啥呢?直接去用ip addr,原始的ip后面是多少,vip后面就保持一致就可以了606a4dc54a352e589b730c1956ba905d.png

具体想深入了解的可以参考:

ip addr详解

https://www.cnblogs.com/wqbin/p/11065587.html

/sbin/arping -I $eth -c 3 -s $onlyvip $gateway":再说下这里 这句话很多网上的脚本都没有,为啥要有?啥作用?是广播vip的 ,切换完成后vip在被绑定的机器上是立刻生效的,但是同局域网内的其他的机器是不会立刻被告知VIP发生了切换了的,所以就需要用arping广播出去,其他机器会立刻感知到VIP执向了新的机器。

五、运行MHA 5.1 检测ssh
[root@nn ~]# masterha_check_ssh --global_conf=/etc/masterha/masterha_default.conf --conf=/etc/masterha/app1.confFri Jan 11 10:11:16 2019 - [info] Reading default configuration from /etc/masterha/masterha_default.conf..Fri Jan 11 10:11:16 2019 - [info] Reading application default configuration from /etc/masterha/app1.conf..Fri Jan 11 10:11:16 2019 - [info] Reading server configuration from /etc/masterha/app1.conf..Fri Jan 11 10:11:16 2019 - [info] Starting SSH connection tests.....#出现一下文本即为检测结果为健康状态Fri Jan 11 10:11:18 2019 - [info] All SSH connection tests passed successfully.You have new mail in /var/spool/mail/root
5.2 检测复制组健康状态
 [root@nn ~]# masterha_check_ssh --global_conf=/etc/masterha/masterha_default.conf --conf=/etc/masterha/app1.confSun Apr 20 18:46:08 2014 - [info] Checking replication health on 192.168.0.60..Sun Apr 20 18:46:08 2014 - [info]  ok.Sun Apr 20 18:46:08 2014 - [info] Checking replication health on 192.168.0.70..Sun Apr 20 18:46:08 2014 - [info]  ok.Sun Apr 20 18:46:08 2014 - [warning] master_ip_failover_script is not defined.Sun Apr 20 18:46:08 2014 - [warning] shutdown_script is not defined.Sun Apr 20 18:46:08 2014 - [info] Got exit code 0 (Not master dead).#出现一下文本即为检测结果为健康状态MySQL Replication Health is OK.
5.3启动 masterha_manager
 masterha_manager --global_conf=/etc/masterha/masterha_default.conf --conf=/etc/masterha/app1.conf --remove_dead_master_conf --ignore_last_failover --ignore_binlog_server_error > /var/log/masterha/app1/app1.log 2>&1 &
说明: --globa l_ conf 为全局配置文件路径 --conf 当前复制组对应的配置文件 --remove_dead_master_conf 失败切换后移除原master配置 --ignore_last_failover 忽略上次失败切换结果 --ignore_binlog_server_error  忽略binlog server错误 5.4 检测masterha_manager运行状态
[root@libothree ~]# masterha_check_status --global_conf=/etc/masterha/masterha_default.conf --conf=/etc/masterha/app1.conf
5.5 停止masterha_manager
masterha_stop --global_conf=/etc/masterha/masterha_default.conf --conf=/etc/masterha/app1.conf
六、MHA运行监控脚本
loghost='10.1.1.1' #日志存储机器loguser='mysqluser'logpwd='pwd'host='10.2.2.2' #MHA所在的机器statuss=($(masterha_check_status  --global_conf=/etc/masterha/masterha_default.conf --conf=/etc/masterha/app1.conf))strs=''for data in ${statuss[@]}do    strs=${strs}" "${data}done  echo ${strs}  mysql -h${loghost} -P3306 -u${loguser} -p${logpwd} slaveinfo -e "INSERT INTO mhaststus(mark,host) VALUES ('${strs}','${host}')"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值