
MHA 概述什么是 MHAMHAMaster High Availability)是一套优秀的 MySQL 高可用环境下故障切换和主从复制的软件。MHA 的出现就是解决 MySQL 单点的问题。MySQL 故障切换过程中MHA 能做到 0-30 秒内自动完成故障切换操作。MHA 能在故障切换的过程中最大程度上保证数据的一致性以达到真正意义上的高可用。为什么要用 MHA为解决 Master 的单点故障无法自动调节的问题。MHA 的组成MHA 由两部分组成: MHAManager (管理节点) MHA Node (数据库节点),MHA Manager 可以单独部署在一台独立的机器上管理多个 master-slave 集群也可以部署在一 台 slave 节点上。MHA Manager 会定时探测集群中的 master 节点。当 master 出现故障时它可以自动将最新数据的 slave 提升为新的 master 然后将所有其他的 slave 重新指向新的 master。MHA 的特点自动故障切换过程中MHA 从宕机的主服务器上保存二进制日志最大程度的保证数据不丢失使用半同步复制可以大大降低数据丢失的风险如果只有一个 slave 已经收到了最新的二进制日 志MHA 可以将最新的二进制日志应用于其他所有的 slave 服务器上因此可以保证所有节点的 数据一致性目前 MHA 支持一主多从架构最少三台服务即一主两从故障切换备选主库的算法1 一般判断从库的是从position/GTID判断优劣数据有差异最接近于 master 的 slave成为 备选主。2 数据一致的情况下按照配置文件顺序选择备选主库。3 设定有权重candidate_master 1按照权重强制指定备选主。1默认情况下如果一个 slave 落后 master 100M 的 relay logs 的话即使有权重也会失效。2如果 check_repl_delay 0 的话即使落后很多日志也强制选择其为备选主。MHA 工作原理目前 MHA 主要支持一主多从的架构要搭建 MHA, 要求一个复制集群必须最少有 3 台数据库服务 器一主二从即一台充当 Master台充当备用 Master另一台充当从库。MHA Node 运行在每台 MySQL 服务器上MHAManager 会定时探测集群中的 master 节点当 master 出现故障时它可以自动将最新数据的 slave 提升为新的 master然后将所有其他的 slave 重新指向新的 masterVIP 自动漂移到新的 master。整个故障转移过程对应用程序完全透明。MHA 部署实施#前面的内容我们已经做好的一主二从复制接下来我们直接进行MHA的安装部署就行了安装Mha相应软件#在所有主机中 [rootMHA ~]# dnf install perl perl-DBD-MySQL perl-CPAN -y [rootMHA ~]# ls anaconda-ks.cfg mha4mysql-manager-0.58-0.el7.centos.noarch.rpm cpan_plugin.tar.gz mha4mysql-node-0.58-0.el7.centos.noarch.rpm [rootMHA ~]# tar zxf cpan_plugin.tar.gz [rootmha MHA-7]# cpan Loading internal logger. Log::Log4perl recommended for better logging CPAN.pm requires configuration, but most of it can be done automatically. If you answer no below, you will enter an interactive dialog for each configuration option instead. Would you like to configure as much as possible automatically? [yes] yes cpan[1] install Config::Tiny cpan[2] install Log::Dispatch cpan[3] install Mail::Sender Specify defaults for Mail::Sender? (y/N) y Default encoding of message bodies (N)one, (Q)uoted-printable, (B)ase64: n cpan[4] install Parallel::ForkManager cpan[5]exit[rootMHA ~]# ls mha4mysql-manager-0.58 mha4mysql-manager-0.58.tar.gz cpan_plugin.tar.gz mha4mysql-manager-0.58-0.el7.centos.noarch.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm #在管理主机中安装MHA管理工具 [rootMHA ~]# rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm --nodeps Verifying... ################################# [100%] 准备中... ################################# [100%] 正在升级/安装... 1:mha4mysql-node-0.58-0.el7.centos ################################# [ 50%] 2:mha4mysql-manager-0.58-0.el7.cent################################# [100%] #在其他mysql主机中 [rootmysql-1 ~]# rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm --nodeps Verifying... ################################# [100%] 准备中... ################################# [100%] 正在升级/安装... 1:mha4mysql-node-0.58-0.el7.centos ################################# [100%]#注意主机之间一定要做免密登录如何主机主机之间可以相互登录否则会检测失败#如下 [rootMHA ~]# ssh -l root 172.25.254.10 Activate the web console with: systemctl enable --now cockpit.socket Register this system with Red Hat Insights: rhc connect Example: # rhc connect --activation-key key --organization org The rhc client and Red Hat Insights will enable analytics and additional management capabilities on your system. View your connected systems at https://console.redhat.com/insights You can learn more about how to register your system using rhc at https://red.ht/registration Last login: Mon Aug 10 14:54:26 2026 from 172.25.254.1 [rootmysql-1 ~]# exit 注销 Connection to 172.25.254.10 closed.配置 MHA 的管理环境因为我们当前只有一套主从所以我们只需要写一个配置文件即可rpm包中没有为我们准备配置文件的模板可以解压源码包后在samples中找到配置文件的模板文件[rootMHA ~]# tar zxf mha4mysql-manager-0.58.tar.gz [rootMHA ~]# cd mha4mysql-manager-0.58/ [rootMHA mha4mysql-manager-0.58]# ls AUTHORS COPYING lib MANIFEST README samples tests bin debian Makefile.PL MANIFEST.SKIP rpm t [rootMHA mha4mysql-manager-0.58]# cd samples/conf [rootMHA conf]# ls app1.cnf masterha_default.cnf [rootMHA conf]# mkdir /etc/masterrha/ [rootMHA conf]# cat masterha_default.cnf app1.cnf /etc/masterrha/app1.cnf [rootMHA conf]# vim /etc/masterrha/app1.cnf [server default] userroot password123 #密码 ssh_userroot #ssh远程登陆用户 repl_userlee #mysql主从复制中负责认证的用户 repl_password123 #mysql主从复制中负责认证的用户密码 master_binlog_dir /data/mysql #二进制日志目录 remote_workdir/tmp #远程工作目录 secondary_check_script masterha_secondary_check -s 172.25.254.10 -s 172.25.254.30 ping_interval3 #每隔3秒检测一次 # master_ip_failover_script /script/masterha/master_ip_failover # shutdown_script /script/masterha/power_manager # report_script /script/masterha/send_report # master_ip_online_change_script /script/masterha/master_ip_online_change [server default] manager_workdir/etc/masterrha #mha工作目录 manager_log/etc/masterrha/manager.log #mha日志 [server1] hostname172.25.254.10 candidate_master1 #可能作为master的主机 check_repl_delay0 [server2] hostname172.25.254.20 candidate_master1 check_repl_delay0 #因为这个候选主在切换的过程中一定是新的master [server3] hostname172.25.254.30 no_master1 #不会作为master的主机[rootMHA conf]# ls app1.cnf masterha_default.cnf [rootMHA conf]# cd [rootMHA ~]# rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm Verifying... ################################# [100%] 准备中... ################################# [100%] 正在升级/安装... 1:mha4mysql-node-0.58-0.el7.centos ################################# [100%] [rootMHA ~]# vim /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm #sub parse_mysql_version($) { # my $str shift; # my $result sprintf( %03d%03d%03d, $str ~ m/(\d)/g ); # return $result; #} # #添加以下内容 sub parse_mysql_major_version($) { my $str shift; my nums $str ~ m/(\d)/g; my $result sprintf( %03d%03d, $nums[0]//0, $nums[1]//0); return $result; } # #注释掉这个内容 #sub parse_mysql_major_version($) { # my $str shift; # my $result sprintf( %03d%03d, $str ~ m/(\d)/g ); # return $result; #} [rootMHA conf]# masterha_manager --help Usage: masterha_manager --global_conf/etc/masterha_default.cnf --conf/usr/local/masterha/conf/app1.cnf See online reference (http://code.google.com/p/mysql-master-ha/wiki/masterha_manager) for details.[rootMHA ~]# masterha_check_ssh --conf/etc/masterrha/app1.cnf #检测网络及 ssh 免密在rhel9中因为perl版本兼容问题会有报错。但是此报错可以忽略 #检测数据主从复制情况 #在所有MySQL主机中 mysql create user root% identified with mysql_native_password by lee; #允许root远程登陆 mysql GRANT ALL ON *.* TO root% ; #执行检测 [rootmysql-mha ~]# masterha_check_repl --conf/etc/masterha/app1.cnfMHA 的故障切换MHA 的故障切换过程共包括以下的步骤1.配置文件检查阶段这个阶段会检查整个集群配置文件配置2.宕机的 master 处理这个阶段包括虚拟 ip 摘除操作主机关机操作3.复制 dead master 和最新 slave 相差的 relay log并保存到 MHA Manger 具体的目录下4.识别含有最新更新的 slave5.应用从 master 保存的二进制日志事件binlog events6.提升一个 slave 为新的 master 进行复制 7.使其他的 slave 连接新的 master 进行复制1.手动切换master无故障切换#注意我们不能切30主机上因为我们定义就是30 不能当master [rootmha conf]# masterha_master_switch \ --conf/etc/masterha/app1.cnf \ --master_statealive \ --new_master_host172.25.254.20 \ --new_master_port3306 \ --orig_master_is_new_slave \ --running_updates_limit10000 Mon Aug 10 22:55:05 2026 - [info] MHA::MasterRotate version 0.58. Mon Aug 10 22:55:05 2026 - [info] Starting online master switch.. Mon Aug 10 22:55:05 2026 - [info] Mon Aug 10 22:55:05 2026 - [info] * Phase 1: Configuration Check Phase.. Mon Aug 10 22:55:05 2026 - [info] Mon Aug 10 22:55:05 2026 - [warning] Global configuration file /etc/masterha_def ault.cnf not found. Skipping. Mon Aug 10 22:55:05 2026 - [info] Reading application default configuration from /etc/masterha/app1.cnf.. Mon Aug 10 22:55:05 2026 - [info] Reading server configuration from /etc/masterh a/app1.cnf.. Mon Aug 10 22:55:06 2026 - [info] GTID failover mode 0 Mon Aug 10 22:55:06 2026 - [info] Current Alive Master: 172.25.254.10(172.25.254 .10:3306) Mon Aug 10 22:55:06 2026 - [info] Alive Slaves: Mon Aug 10 22:55:06 2026 - [info] 172.25.254.20(172.25.254.20:3306) Version8 .3.0 (oldest major version between slaves) log-bin:enabled Mon Aug 10 22:55:06 2026 - [info] Replicating from 172.25.254.10(172.25.254. 10:3306) Mon Aug 10 22:55:06 2026 - [info] Primary candidate for the new Master (cand idate_master is set) Mon Aug 10 22:55:06 2026 - [info] 172.25.254.30(172.25.254.30:3306) Version8 .3.0 (oldest major version between slaves) log-bin:enabled Mon Aug 10 22:55:06 2026 - [info] Replicating from 172.25.254.10(172.25.254. 10:3306) Mon Aug 10 22:55:06 2026 - [info] Not candidate for the new Master (no_maste r is set) It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before swi tching. Is it ok to execute on 172.25.254.10(172.25.254.10:3306)? (YES/no): yes#查看集群状态 [rootmysql-1 ~]# mysql -uroot -p123 -e show slave status\G; | head -n 15 mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 172.25.254.20 Master_User: lee Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-binlog.000046 Read_Master_Log_Pos: 158 Relay_Log_File: mysql-1-relay-bin.000002 Relay_Log_Pos: 331 Relay_Master_Log_File: mysql-binlog.000046 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB:[rootmysql-3 ~]# mysql -uroot -p123 -e show slave status\G; | head -n 15 mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 172.25.254.20 Master_User: lee Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-binlog.000046 Read_Master_Log_Pos: 158 Relay_Log_File: mysql-3-relay-bin.000002 Relay_Log_Pos: 331 Relay_Master_Log_File: mysql-binlog.000046 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB:master故障后切换[rootmysql-1 ~]# systemctl stop mysqld.service [rootmha ~]# masterha_master_switch --master_statedead --conf/etc/masterha/app1.cnf --dead_master_host172.25.254.10 --dead_master_port3306 --new_master_host172.25.254.20 --new_master_port3306 --ignore_last_failover#查看切换信息 [rootmysql-node3 ~]# mysql -uroot -plee -e show slave status\G; | head -n 15 mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 172.25.254.20 Master_User: lee Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 2337 Relay_Log_File: mysql-node3-relay-bin.000002 Relay_Log_Pos: 422 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB:#故障恢复 #当出现故障切换后mha主机中会出现切换锁文件当文件存在后不能再次执行切换 [rootmha ~]# ls /etc/masterha/ app1.cnf app1.failover.complete mha.log scripts [rootmysql-1 ~]# systemctl restart mysqld.service [rootmha ~]# rm -fr /etc/masterha/app1.failover.complete [rootmysql-node2 ~]# mysql -uroot -plee -e reset slave;mysql CHANGE MASTER TO - MASTER_HOST172.25.254.20, - MASTER_USERlee,MASTER_PASSWORD123, - MASTER_LOG_FILEmysql-binlog.000046, - MASTER_LOG_POS158; Query OK, 0 rows affected, 8 warnings (0.02 sec) mysql start slave; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql show slave status;\G[rootmysql-node1 ~]# mysql -uroot -plee -e start slave; [rootmysql-node1 ~]# mysql -uroot -plee -e show slave status\G; | head -n 15 mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 172.25.254.20 Master_User: lee Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 2337 Relay_Log_File: mysql-node1-relay-bin.000002 Relay_Log_Pos: 422 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB:自动切换[rootmha masterha]# masterha_manager --conf/etc/masterha/app1.cnf Mon Aug 10 23:53:23 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping. Mon Aug 10 23:53:23 2026 - [info] Reading application default configuration from /etc/masterha/app1.cnf.. Mon Aug 10 23:53:23 2026 - [info] Reading server configuration from /etc/masterha/app1.cnf.. [rootmha masterha]# jobs [1] 运行中 masterha_manager --conf/etc/masterha/app1.cnf [rootmha masterha]# Creating /tmp if not exists.. ok. Checking output directory is accessible or not..[rootmysql-1 mysql]# systemctl stop mysqld.service [rootmysql-3 ~]# mysql -uroot -p123 -e show slave status\G; | head -n 15 mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for source to send event Master_Host: 172.25.254.20 Master_User: lee Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-binlog.000046 Read_Master_Log_Pos: 158 Relay_Log_File: mysql-3-relay-bin.000002 Relay_Log_Pos: 331 Relay_Master_Log_File: mysql-binlog.000046 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB:可以看到之前是10 现在10被停止了所以30自动切换到了20 上vip功能及vip的启动切换[rootmysql-1 ~]# ip a 1: lo: LOOPBACK,UP,LOWER_UP mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:11:d0:1c brd ff:ff:ff:ff:ff:ff altname enp3s0 altname ens160 inet 172.25.254.10/24 brd 172.25.254.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet 172.25.254.100/24 scope global secondary eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe11:d01c/64 scope link noprefixroute valid_lft forever preferred_lft forever #vip 从20 迁移到 10 [rootmysql-2 ~]# ip a 1: lo: LOOPBACK,UP,LOWER_UP mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:d9:89:68 brd ff:ff:ff:ff:ff:ff altname enp3s0 altname ens160 inet 172.25.254.20/24 brd 172.25.254.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fed9:8968/64 scope link noprefixroute valid_lft forever preferred_lft forever[rootmha ~]# vim /etc/masterha/app1.cnf master_ip_failover_script /etc/masterha/scripts/master_ip_failover master_ip_online_change_script /etc/masterha/scripts/master_ip_online_change [rootmha ~]# vim /etc/masterha/scripts/master_ip_failover my $vip 172.25.254.100/24; [rootmha ~]# vim /etc/masterha/scripts/master_ip_online_change my $vip 172.25.254.100/24; [rootmysql-node1 ~]# ip a a 172.25.254.100/24 dev eth0[rootmha masterha]# chmod x master_ip_failover master_ip_online_change [rootmha masterha]# masterha_master_switch --conf/etc/masterha/app1.cnf --master_statealive --new_master_host172.25.254.10 --new_master_port3306 --orig_master_is_new_slave --running_updates_limit10000其他故障更手动切换是一样的