MHA

相关脚本

#manager节点
[root@kmissitdb05 bin]# ls -l /usr/bin | grep masterha
-rwxr-xr-x  1 root root       1995 Oct 11  2017 masterha_check_repl
-rwxr-xr-x  1 root root       1779 Oct 11  2017 masterha_check_ssh
-rwxr-xr-x  1 root root       1865 Oct 11  2017 masterha_check_status
-rwxr-xr-x  1 root root       3201 Oct 11  2017 masterha_conf_host
-rwxr-xr-x  1 root root       2517 Oct 11  2017 masterha_manager
-rwxr-xr-x  1 root root       2165 Oct 11  2017 masterha_master_monitor
-rwxr-xr-x  1 root root       2373 Oct 11  2017 masterha_master_switch //切换脚本
-rwxr-xr-x  1 root root       5171 Oct 11  2017 masterha_secondary_check
-rwxr-xr-x  1 root root       1739 Oct 11  2017 masterha_stop
#node节点
/usr/bin/apply_diff_relay_logs
/usr/bin/filter_mysqlbinlog
/usr/bin/purge_relay_logs
/usr/bin/save_binary_logs

purge_relay_log

参数

MySQL数据库主从复制在默认情况下从库的relay logs会在SQL线程执行完毕后被自动删除。但是在relay_log_purge = 0和在 MHA 集群中,若配置了 purge_relay_log=1,即使 relay_log_purge=0,MHA 也会自动清理(仅保留最后 3 个文件)。

SHOW SLAVE STATUS\G
*************************** 1. row ***************************
...
Relay_Log_File: mysql-relay-bin.000123  -- SQL 线程当前正在应用的 relay log
Relay_Log_Pos: 123456                   -- SQL 线程执行到的位置
Master_Log_File: mysql-bin.000100       -- IO 线程从主库读取的 binlog
Read_Master_Log_Pos: 654321             -- IO 线程读取的主库 binlog 位点

1、MySQL relay_log_purge=1 + MHA purge_relay_log=1

生成 relay log:
主库写入大量数据,从库生成 relay log(如 mysql-relay-bin.000101 至 mysql-relay-bin.000110)。
自动清理行为:
MySQL 自动删除已处理的文件(如 000101 至 000107)。
MHA 保留策略生效:作为冗余清理机制。
即使 000108、000109、000110 已处理完,MHA 仍会保留这最后 3 个文件。

2、MySQL 配置 relay_log_purge=1,MHA 未配置purge_relay_log=1

Relay Log 清理逻辑
MySQL 自动清理:
SQL 线程处理完一个 relay log 文件后,立即自动删除该文件。
默认行为下,已处理的 relay log 不会堆积。
MHA 不干预:
因未启用 purge_relay_log=1,MHA 不会触发额外的清理动作。

MHA 在故障切换(Failover)过程中,为了确保数据完整性,会临时设置 relay_log_purge=0,禁用自动清理因为MHA 需要依赖 relay log 修复其他从库的复制状态,保留日志可提供回退和修复的余地。

MHA 完成切换后,默认不会恢复原 relay_log_purge值,需手动检查配置。

purge_relay_log脚本

purge_relay_logs 是 MHA 提供的一个工具脚本,用于安全删除从库上已处理的 relay log

脚本清理 relay log 的步骤:

步骤 操作 文件系统状态
1. 创建硬链接 将原 relay log 文件(如 mysql-relay-bin.000123)在 --workdir 下创建硬链接副本。 原文件和新硬链接共享同一 inode,引用计数变为 2。
2. 执行 PURGE 命令 通过 PURGE RELAY LOGS 删除原 relay log 文件。 原文件的文件名被删除,引用计数减 1(变为 1),但数据仍通过硬链接保留。应用还持有inode,所以其他应用还能操作该文件。
3. 删除硬链接 脚本完成后,自动删除 --workdir 中的硬链接文件。 引用计数归零,数据块被释放,磁盘空间真正回收。

用法:

Usage:   purge_relay_logs --user=root --password=rootpass --host=127.0.0.1
参数描述 
--user    用户名,缺省为root 
--password mysql     密码 
--port          端口号 
--host          主机名,缺省为127.0.0.1 
--workdir    指定创建relay log的硬链接的位置,默认是/var/tmp,成功执行脚本后,硬链接的中继日志文件被删除,由于系统不同分区创建硬链接文件会失败,故需要执行硬链接具体位置,建议指定为relay log相同的分区 
--disable_relay_log_purge 默认情况下,参数relay_log_purge=1,脚本不做任何处理,自动退出              设定该参数,脚本会将relay_log_purge设置为0,当清理relay log之后,最后将参数设置为OFF(0)

和MHA的purge_relay_log的关系

purge_relay_logs 实际执行清理操作的底层工具 可独立运行,无需 MHA 配置文件参数触发。
purge_relay_log=1 控制 MHA 是否自动调用 purge_relay_logs 脚本的开关 依赖此配置,MHA 才会在后台触发清理动作。
#手动调用
purge_relay_logs --user=mha_user --password=xxx --host=slave_ip --workdir=/tmp
# 保留最后 2 个文件(覆盖默认值)
purge_relay_logs --user=mha_user --password=xxx --host=slave_ip --keep_relay_log_count=2

配置文件

范围

#global scope全局范围的
/etc/masterha_default.cnf
[server default]  -- 这下面的都是全局配置,适用于所有app.cnf
user=dba
password=dba
ssh_user=root
master_binlog_dir= /data/mysql.bin
secondary_check_script= masterha_secondary_check -s remote_host1 -s remote_host2
ping_interval=3
master_ip_failover_script=/script/masterha/master_ip_failover
shutdown_script= /script/masterha/power_manager
report_script= /script/masterha/send_master_failover_mail
#某一个集群范围的
/etc/app1.cnf
# application scope,[server default] 里面的这些配置,会影响到下面的N 个 server
[server default]
remote_workdir=/var/log/masterha/app1
manager_workdir=/var/log/masterha/app1
manager_log=/var/log/masterha/app1/app1.log
# local scope 每个server下面的配置,专属于某个server
[server1]
hostname=192.168.1.10
candidate_master=1
[server2]
hostname=192.168.1.11
candidate_master=1
[server3]
hostname=192.168.1.12
no_master=1

配置参数

##MHA 参数列表##
Local : 指每一个配置块内部。 Local功能的参数需要放置在[server_xxx] 块下面
App : 参数作用于master/slave, 这些参数需要配置在[server_default]块的下面
Global : 作用于master/slave, Global级别的参数用于管理多组master/slave结构,可以统一化管理一些参数。
#用户
user:管理着MySQL的stop slave等,最好是root用户。
ssh_user:登录到node节点上的,还要执行读取差异日志等,最好是root用户
repl_user:复制用户
-----------------------------------------------------------------------------------------
#hostname
配置MySQL服务器的机器名或是IP地址,这个配置项是必须的,而且只能配置在[server_xxx]这个块下面。
如:
参数名	是否必须	作用域	默认值	例子及说明
hostname	Yes	Local Only	–	hostname=mysql_server1, hostname=192.168.0.1, 
#ip
MySQL服务器的ip地址。 默认从gethostname($hostname)中获得。 默认不用配置这个参数,MHA可以通过hostname自动获取,MHA通过IP地址连接MySQL服务器及SSH连接。
如:
参数名	是否必须	作用域	默认值	例子及说明
ip	No	Local Only	通过gethostbyname($hostname)获得	ip=192.168.1.3
#port
MySQL运行的端口号。 默认是3306. MHA使用IP和端口号连接MySQL
如:
参数名	是否必须	作用域	默认值	例子及说明
port	No	Local/App/Glbal	3306	port=3306
#ssh_host
(从MHA 0.53后开始支持) MHA要ssh上MySQL目标服务器使用hostname 或是ip地址。这个参数主要用于在使用多个VLAN的环境中。为了安全原因ssh默认不允许。默认这个参数和hostname相同。
如:
参数名	是否必须	作用域	默认值	例子及说明
ssh_host	No	Local Only	和hostname相同	ssh_host=mysql_server1, ssh_host=192.168.0.1, 
#ssh_ip
(从MHA 0.53后开始支持) 和ssh_host作用相同。 默认是gethostname($ssh_host)获得。 
如:
参数名	是否必须	作用域	默认值	例子及说明
ssh_ip	No	Local Only	gethostbyname($ssh_host)	ssh_ip=192.168.1.3
#ssh_port
(从MHA 0.53后开始支持) SSH使用的端口号,默认是22.
如:
参数名	是否必须	作用域	默认值	例子及说明
ssh_port	No	Local/App/Global	22	ssh_port=22
#ssh_connection_timeout
(从MHA 0.54后支持)默认是5秒。在没添加这个参数之前ssh超时时间是写死的。
如:
参数名	是否必须	作用域	默认值	例子及说明
ssh_connection_timeout	No	Local/App/Global	5	ssh_connect_timeout=5
#ssh_options
(从MHA 0.53后支持) 添加ssh命令行的支持参数,例如加上特别文件名的key的支持等。
如:
参数名	是否必须	作用域	默认值	例子及说明
ssh_options	No	Local/App/Global	“” 空的	ssh_options=”-i /root/.ssh/id_dsa2″
#candidate_master
你可能对于同一组slave中有着不同的规划,有的其望在Master故障时,提升为新的Master(如: Raid1的slave比Raid0的slave更适合做Master)
这个参数的作用是当设计candidate_master = 1时,这个服务器有较高的优先级提升为新的master(还要具备: 开启binlog, 复制没有延迟)。 所以当设置了candidate_master = 1的机器在master故障时必然成为新的master. 但这是很有用的设置优先级的一个参数。
如果设置了多台机器的caddidate_master = 1 , 优先策略依赖于块名字([server_xxx]). [server_1] 优衔权高于[server_2].
如:
参数名	是否必须	作用域	默认值	例子及说明
candidate_master	No	Local Only	0	candidate_mast=1
#no_master
当设置了no_master = 1的服务器,这个服务器永远不会提升为新的master. 这个参数据对于永远不期望成为master的机器很有用。 如: 你可能需要在使用raid0的机器上设置no_master = 1 或是你希望在远程的idc里运行一个slave. 注意: 当没有可以成为新master的机器是MHA就直接退出来了同时停止监控和master故障切换。
如:
参数名	是否必须	作用域	默认值	例子及说明
no_master	No	Local Only	0	no_master=1
#ignore_fail
在默认情况下,MHA manager不会在slave存在故障的情况下(已经不能通过SSH/MySQL进行连接,或是SQL Thread已经停止出错,其它原因)的情况下进行Master的故障切换(当不存在slave时MHA manager也会退出)。 但有些情况下你期望在slave存在问题的情况下,也进行故障切换。 所以当设置了ignore_fail = 1时,MHA会在所有的机器有问题的时间也会进行故障切换。 默认是0.
如:
参数名	是否必须	作用域	默认值	例子及说明
ignore_fail	No	Local Only	0	ignore_fail=1
#skip_init_ssh_check#
在MHA manager启动时跳过ssh检查。
如:
参数名	是否必须	作用域	默认值	例子及说明
skip_init_ssh_check	No	Local Only	0	skip_init_ssh_check=1
#skip_reset_slave
(从MHA 0.56开始支持) Master故障切换后新的master上执行RESET SLAVE(ALL).
如:
参数名	是否必须	作用域	默认值	例子及说明
skip_reset_slave	No	Local/App/Global	0	skip_reset_slave=1
#user
用于管理MySQL的用户名。这个最后需要root用户,因为它需要执行:stop slave; change master to , reset slave. 默认: root
如:
参数名	是否必须	作用域	默认值	例子及说明
user	No	Local/App/Global	root	user=mysql_root
#password
MySQL的管理用户的密码。 默认是空的
如:
参数名	是否必须	作用域	默认值	例子及说明
password	No	Local/App/Global	空的	password=rootpass
#repl_user
MySQL用于复制的用户,也是用于生成CHANGE MASTER TO 每个slave使用的用户。 这个用户必须有REPLICATION SLAVE权限在新的Master上。默认情况下 repl_user会在将来成为master的机器上运行show slave status获取到。
如:
参数名	是否必须	作用域	默认值	例子及说明
repl_user	No	Local/App/Global	从show slave status	repl_user=repl
#repl_password
MySQL中repl_user用户的密码。 默认是当前复制用的密码。  当你使用online_master_switch时,当使用–orig_master_is_new_slave(原来的Master成为新Master的一个slave)时,如果没有repl_password 开启同步就会失败了。因为当前master上用于复制的用户名和密码都是空的(MHA在原来的Master上执行change master to 时没有带复制的密码,虽然其它slave上设置了复制的密码)
如:
参数名	是否必须	作用域	默认值	例子及说明
repl_password	No	Local/App/Global	当前复制用的密码	repl_password=replpas
#disable_log_bin
当设置了这个参数,在slave应用差异的relay log时不会产生二进制日志。 内部实现通过mysqlbinlog的disable-log-bin实现。
如:
参数名	是否必须	作用域	默认值	例子及说明
disable_log_bin	No	Local/App/Global	0	disable_log_bin=1
#master_pid_file
指定MySQL的pid文件。 这个参数在一台服务器上运行多个MySQL服务进程时非常有用。
如:
参数名	是否必须	作用域	默认值	例子及说明
master_pid_file	No	Local/App/Global	–	master_pid_file=/var/lib/mysql/master1.pid
#ssh_user
MHA Mananger, MHA node系统上的用户。 这个帐号需要在远程机器上有执行权限(Manager->MySQL),在slave成员之间复制差异的relay-log(MySQL->MySQL)
这个用户必须有读取MySQL的binary/relay日志和relay_log.info的权限,还需要对远程MySQL上remote_workdir目录的写权限。
这个用户还必须可以直接ssh到远程机顺上, 推荐使用ssh pbulic key . 一般使用的ssh_user也是运行manager那个那个用户。
如:
参数名	是否必须	作用域	默认值	例子及说明
ssh_user	No	Local/App/Global	当前使用的系统用户	ssh_user=root
#remote_workdir
MHA node上工作目录的全路径名。如果不存在,MHA node会自动创建,如果不允许创建,MHA Node自动异常退出。 需要注意MHA manager 或是MHA node上需要检查空间是否可用,所以需要注意检查这个。 一般默认, remote_workdir是的”/var/tmp”
如:
参数名	是否必须	作用域	默认值	例子及说明
remote_workdir	No	Local/App/Global	/var/tmp	remote_workdir=/var/log/masterha/app1
#master_binlog_dir
master上用于存储binary日志的全路径。这个参数用于当master上mysql死掉后,通过ssh连到mysql服务器上,找到需要binary日志事件。这个参数可以帮助用于无法找到master进程死掉后binary日志存储位置。
一般: master_binlog_dir是”/var/lib/mysql/, /var/log/mysql”. “/var/lib/mysql/”是大多数系统发行版本的存放位置,”/var/log/mysql”是ubuntu发行版本的存放位置。 你也可以设置多个存放位置用逗号隔开。
如:
参数名	是否必须	作用域	默认值	例子及说明
master_binlog_dir	No	Local/App/Gobal	/var/lib/mysql	master_binlog_dir=/data/mysql1,/data/mysql2
#log_level
设置MHA manager记录LOG的级别。 默认是info级别而且大多数情况也是比较适合。 同样可以设置为: debug/info/warning/error.
如:
参数名	是否必须	作用域	默认值	例子及说明
log_level	No	App/Global	info	log_level=debug
#manager_workdir :临时文件、状态标记、差异日志
用于指定mha manager产生相关状态文件全路径。 如果没设置 默认是/var/tmp
如:
参数名	是否必须	作用域	默认值	例子及说明
manager_workdir	No	App	/var/tmp	manager_workdir=/var/log/masterha
#manager_log :	运行日志(文本文件)
指定mha manager的绝对路径的文件名日志文件。 如果没设置MHA Manager将打印到STDOUT/STDERR。 当手工执行故障切换(交互模式切换),MHA Manager会忽略manager_log设置直接将日志输出到STDOUT/STDERR.
如:
参数名	是否必须	作用域	默认值	例子及说明
manager_log	No	App	STDERR	manager_log=/var/log/masterha/app1.log
#check_repl_delay
在默认情况下,当一个slave同步延迟超过100M relay log(需要应用超过100M relay log), MHA在做故障切换时不会选择这个slave做为新的master,因为恢复需要经过很长时间.当设置了check_repl_delay = 0, MHA将忽略被选择的slave上的同步延迟。 这个选项在设置了candidate_master = 1特声明的期望这台机器成为master的情况下特别有用。
如:
参数名	是否必须	作用域	默认值	例子及说明
check_repl_delay	No	App/Golbal	1	check_repl_delay=0
#check_repl_filter
在默认下情况,当master和slave设置了不同了binary log/replication 过滤规则时,MHA直接报错不会进行监控和故障切换。 这些将会导致出现一些异想不到的错误”Table not exists”。如果你100%确认不同的过滤规则不会导致恢复中的错误,设置check_repl_filter=0。 需要注意: 当使用了check_repl_filter = 0时,MHA不会检查过滤规则在应用差异的relay日志,所以有可能会出现”Table not exists”的错误。当你设置了这个参数请小心处理。
如:
参数名	是否必须	作用域	默认值	例子及说明
check_repl_filter	No	App/Global	1	check_repl_filter=0
#latest_priority
在默认情况下,和Master最接近的slave(一个slave从Master上获得了最一个binlog事件)是最有优先权成为新的master。 如果你想控制一下切换的策略(如: 先选择host2,如果不行,选host3;host3不行,选host4…) 那么设置latest_priority = 0 就可以了。
如:
参数名	是否必须	作用域	默认值	例子及说明
latest_priority	No	App/Global	1	latest_priority=0
#multi_tier_slave
从MHA 0.52开始, 多层复制可以支持了。在默认情况下,不支持三层或是更多层的复制配置。 如果: host2从host1上复制,host3从host2上复制。 在默认配置的情况下不支持写host{1,2,3},因为这是一个三层的复制,MHA Manager会停止报错。 当设置了multi_tier_slave, MHA Manager就不会在三层复制报错停止。 但是会忽略第三层的机器。也就是如果host1挂了,host2将会成为新的master,host3还是从host2上进行复制。
这个参数在MHA Manager 0.52后的版开始支持。
如:
参数名	是否必须	作用域	默认值	例子及说明
muli_tier_slave	No	App/Global	0	multi_tier_slave=1
#ping_interval
这个参数设置MHA Manager多长时间去ping一下master(执行一些SQL语句). 当失去和master三次偿试,MHA Manager会认为MySQL Master死掉了。也就是说,最大的故障切换时间是4次ping_interval的时间,默认是3秒。
如果MHA Manager在和MySQL创建连接时都收到多连接错误或是认证错误,这个就不做重试就会认为master已经挂掉。
如:
参数名	是否必须	作用域	默认值	例子及说明
ping_interval	No	App/Global	3	ping_interval=5
#ping_type
(从MHA 0.53后开始支持) 在默认情况下, MHA manager和MySQL创建一个连接执行”select 1″(ping_type=select)用于检查master是否健康。 但有一些情况: 每次检测都连接/然后断开会比较好一点,这样对于tcp方面的错误感知更快一点。设置ping_type=CONNECT 就行了。从MHA 0.56后pint_type=INSERT也被添加。
如:
参数名	是否必须	作用域	默认值	例子及说明
ping_type	No	App/Global	SELECT	ping_type=CONNECT
ping_type=CONNECT 通过 每次新建 TCP 连接 强制验证网络层的可用性,避免了长连接假死和 TCP 重试机制的延迟问题,代价是更高的 TCP 连接开销。
ping_type=selectMHA Manager 与 MySQL 主库建立一个 长连接,并定期通过执行 SELECT 1 查询来检查主库是否存活。应用层(MHA)需等待查询超时才能感知问题,响应延迟可能较长。
#secondary_check_script
一般来讲, 非常推荐使用更多网络上机器是不同路由策略上的机器来检查MySQL Master是否存活。 默认情况下,只有MHA Manager通过一个路由来检查Master是否存活。这个也是不推荐的。MHA可以通过外部secondary_check_script配置的脚本来做到从多个路由策略下进行检查。
secondary_check_script = masterha_secondary_check -s remote_host1 -s remote_host2
secondary_check_script包含在MHA Manager发行包中。 MHA中内置的secondary_check_script在大多数情况下工作良好,但并不是任何地都可以使用这个脚本。
secondary_check_script通过SSH连接到远程主机,然后从那里发起对Master的TCP连接检查
2. 远程主机的必备条件
需求	            说明
SSH 公钥信任	 MHA Manager 需配置到 remote_host1、remote_host2 的免密 SSH 登录。
Perl 环境	      脚本依赖 IO::Socket::INET 模块(Perl 5.6+ 默认包含)。
网络连通性	    远程主机需能通过 TCP 连接到 MySQL Master 的端口(如 3306)。
在上面的例子中, MHA Manager通过Manager->(A)->remote_host1->(B)->master_host 和Manager->(A)-remote_host2->(B)->master_host来检查MySQL master是否存活。如果在连接过程中通过A可以都成功,通过B是都失败,secondary_\check_\script返回0,而且认为master已经死掉,进行故障切换。如果通过A成功,但返回代码为: 2,则MHA manager有会认为是网络问题,则不会进行故障切换。如果A成功,B也成功,masterha_secondary_check 退出返回:3 则MHA Manager就为认为MySQL Master为存活状态, 则不会进行故障切换。
一般来讲, remote_host1和remote_host2是和MHA Manager及MySQL Server位于不同的网段中。
MHA会调用secondary_check_script声明的脚本并自动带上一些参数。 masterha_secondary_check在很多场景都是适用的,但是你也可以自已实现这个程序带有更多的功能。
–user=(在远程机器上使用的SSH用户名。 ssh_user的值将被使用)
–master_host = (master的hostname)
–master_ip = (master的ip地址)
–master_port = ( master的端口号)
注意: 内置的masterha_secondary_check脚本依赖于的Perl的IO::Socket::INET(Perl 5.6.0中是默认支持包含这个模块)。 masterha_secondary_check需要通过ssh连接到远程的机器上,所以需要manager到远程机器上建立public key信任。另外masterha_secondary_check是通过和Master建立TCP的连接测试Master是否存活,所以mysql设置的max_connections不起作用。 但每次TCP连接成功后,MySQL的Aborted_connects 值都会加1。
如:
参数名	是否必须	作用域	默认值	例子及说明
secondary_check_script	No	App/Global	null	secondary_check_script= masterha_secondary_check -s remote_dc1 -s remote_dc2
#master_ip_failover_script
如:
参数名	是否必须	作用域	默认值	例子及说明
master_ip_failover_script	No	App/Global	null	master_ip_failover_script=/usr/local/custom_script/master_ip_failover
#master_ip_online_changes_script
这个参数有点类似于master_ip_failover_script,但这个参数不用于master 故障转意,只使用到master在线的切换。
冻结Master写的过程:
–command=stop or stopssh 
–orig_master_host = (当前master的主机名) 
–orig_master_ip = (当前master的ip地址) 
–orig_master_port = (当前master的port端口号) 
–orig_master_user = (当前master的用户) 
–orig_master_password = (当前master的用户名的密码) 
–orig_master_ssh_user = (从0.56支持,当前master的ssh的用户名)
–orig_master_is_new_slave =  (从 0.56 ,是否把原Master更改为新的slave)
新的Master接受写的过程:
–command=start 
–orig_master_host = ( 原master的机器名 ) 
–orig_master_ip = ( 原master的ip ) 
–orig_master_port = ( 原master的端口号 ) 
–new_master_host = (新master的机器名) 
–new_master_ip = (新master的ip) 
–new_master_port = (新master的端口号) 
–new_master_user = (新master上的用户名) 
–new_master_password = (新master上的用户名及密码) 
–new_master_ssh_user = (从0.56支持, 新master上的ssh用户)
MHA在冻结写的切换过程中会在Master上执行FlUSH TABLES WITH READ LOCK,在这个优雅的切换过程不会有任何写入的。在新的Master在开始授权写的过程中,你可以做和master_ip_failover_script一样的事情。 例如: 创建用户及权限, 执行set global read_only=0, 更新数据库路由表竺。 如果脚本执行退出码不是0 或是10, MHA Manager异常退出并发不会继续进行master切换。
默认这个参数是空的,所以MHA Manager在默认情况下什么也不做。
可以在(MHA Manager package)/samples/scripts/master_ip_online_change。里找到例子脚本。例子脚本包含于MHA Manager源文件或是GitHub的分支中。
如:
参数名	是否必须	作用域	默认值	例子及说明
master_ip_online_change_script	No	App/Global	null	master_ip_online_change_script= /usr/local/custom_script/master_ip_online_change
#shutdown_script
如:
参数名	是否必须	作用域	默认值	例子及说明
shutdown_script	No	App/Global	null	shutdown_script= /usr/local/custom_script/master_shutdown
report_script
在Master故障完毕后,也许想发一个送一个报告(如email)报告一下切换完毕或是发生的错误。report_script可以完成这个工作。MHA Manager可以通过以下参数使用:
–orig_master_host = (死掉master机器名)
–new_master_host = (新的master机器名)
–new_slave_hosts = (新的slave机器名列表,用逗号隔开)
–subject = (邮件名)
–body = (正文)
默认这些参数是空的。 所以默认MHA Manager什么事情也不做。
可以在(MHA Manager package)/samples/scripts/send_report里找到例子脚本。例子脚本包含于MHA Manager源文件或是GitHub的分支中。
如:
参数名	是否必须	作用域	默认值	例子及说明
report_script	No	App/Global	null	report_script= /usr/local/custom_script/report
#init_conf_load_script
这个参数用于不想设置明文在配置文件中(如:密码相关)。 只用返回”name=value”这样的值。 这个可以用来复盖global配置中的一些值。一个例子脚本如下。
#!/usr/bin/perl
print “password=$ROOT_PASS\n”;
print “repl_password=$REPL_PASS\n”;
如:
参数名	是否必须	作用域	默认值	例子及说明
init_conf_load_script	No	App/Global	null	report_script= /usr/local/custom_script/init_conf_loader
dead_master_host 不是 MHA 配置文件中的固定参数,而是手动触发故障转移时通过命令行动态传入的参数。
–orig_master_port 这些参数需要动态指定,不出现在配置文件里面

Master High Available

MasterFailover

masterha_manager是持续监控主库并自动触发故障转移的守护进程,而masterha_master_switch用于手动或计划性切换。

1. 认为只有manager进程才能执行故障转移,而实际上手动命令也可以独立执行。
2. 未意识到故障转移标记文件的存在可能导致后续操作被阻止,即使manager未运行。
3. 混淆了停止manager进程和停止整个MHA功能,认为停止manager后所有相关操作都会终止,但实际上手动命令仍可执行。
manage和node之间,可以通过manage主动发起,也可以通过脚本被动发起,node还会执行的

自动触发与手动触发的对比

场景 触发条件 核心流程 依赖进程 依赖文件
自动触发(Manager进程) Manager 进程持续监控主库状态(通过 ping_interval和ping_type配置),当连续失败次数超过 max_ping_errors时触发故障转移。 Phase 1 ~ Phase 5 MHA Manager 进程需持续运行 自动触发会检查故障转移标记文件(如 app1.failover.complete),若上次故障转移时间在 failover_duration_threshold(默认 8 小时)内,可能跳过本次切换(除非指定 --ignore_last_failover)
手动触发(命令行) 用户主动执行命令,通过 --master_state=dead 参数跳过主库存活检查,直接进入故障转移流程。 Phase 1 ~ Phase 5 无需 Manager 进程运行 除非显式指定 --ignore_last_failover,否则仍会检查 failover_duration_threshold

自动转移或者手动触发转移都要经过这些步骤

#无GTID模式
-----------------------------------------------------------------------------------------
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..
	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 slave
Phase 5: New master cleanup phase..
	reset_slave_on_new_master
	在new master上执行reset slave all;
#GTID模式
-----------------------------------------------------------------------------------------
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,除非配置了额外的参数 ingnore那个参数。
		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 master

Phase 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;

MasterRotate

#(Non-GTID)
Phase 1: Configuration Check Phase
 do_master_online_switch
-----------------------------------------------------------------------------------------
#检查原主
identify_orig_master
* read_config():
    Reading default configuration from /etc/masterha_default.cnf..
    Reading application default configuration from /etc/app1.cnf..
    Reading server configuration from /etc/app1.cnf..

* connect_all_and_read_server_status:
    connect_check: 首先进行connect check,确保各个server的MySQL服务都正常
    connect_and_get_status:
            获取MySQL实例的server_id/mysql_version/log_bin..等信息
            通过执行show slave status,获取当前的master节点。如果输出为空,说明当前节点是master节点( 0.56已经不是这么判断了,已经支持multi master)
    validate_current_master:取得master节点的信息,并判断配置的正确性
    check是否有server down,若有则退出rotate
    check master alive or not,若dead则退出rotate
    check_repl_priv:
        查看用户是否有replication的权限
    获取monitor_advisory_lock,以保证当前没有其他的monitor进程在master上运行
        执行:SELECT GET_LOCK('MHA_Master_High_Availability_Monitor', ?) AS Value
    获取failover_advisory_lock,以保证当前没有其他的failover进程在slave上运行
        执行:SELECT GET_LOCK('MHA_Master_High_Availability_Failover', ?) AS Value
    check_replication_health:
        执行:SHOW SLAVE STATUS来判断如下状态:current_slave_position/has_replication_problem
        其中,has_replication_problem具体check如下内容:IO线程/SQL线程/Seconds_Behind_Master(1s)
    get_running_update_threads:
        使用show processlist来查询当前有没有执行update的线程存在,若有则退出switch
    $self->validate_current_master():
        检查是否是GTID模式
-----------------------------------------------------------------------------------------
#检查新主
identify_new_master
  set_latest_slaves:当前的slave节点都是latest slave
   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 2: Rejecting updates Phase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1、reject_update
* lock table来reject write binlog
      调用master_ip_online_change_script --command=stop
      如果MHA的配置文件中设置了"master_ip_online_change_script"参数,则执行该脚本来disable writes on the current master
      该脚本在使用了vip的时候,在origin master上删除vip{可选}
      reconnect:确保当前与master的连接正常
      lock_all_tables:执行FLUSH TABLES WITH READ LOCK,来lock table
      check_binlog_stop:连续两次show master status,来判断写binlog是否已经停止
2、read_slave_status
get_alive_slaves:
  check_slave_status:调用"SHOW SLAVE STATUS"来取得slave的信息:
3、switch_master
  switch_master_internal:
    master_pos_wait:调用select master_pos_wait函数,等待主从同步完成
    get_new_master_binlog_position:通过'show master status'来获取
  Allow write access on the new master:
    调用master_ip_online_change_script --command=start ...,将vip指向new master
  disable_read_only:
    在新master上执行:SET GLOBAL read_only=0
4、switch_slaves
  switch_slaves_internal:
    change_master_and_start_slave
        change_master:
        start_slave:
  unlock_tables:在orig master上执行unlock table
Phase 3: New master cleanup phase
  reset_slave_on_new_master
  release_failover_advisory_lock
  
#GTID
GTID模式的online switch 和 non-GTID 流程一样,除了在change_master_and_start_slave 不一样之外

测试

检查manage节点

[root@kmissitdb05 etc]# masterha_check_status --conf=/opt/mysqlRds/etc/mha.cnf
mha is stopped(2:NOT_RUNNING).
[root@kmissitdb05 etc]# masterha_check_status --conf=/opt/mysqlRds/mha.cnf
Got error on conf /opt/mysqlRds/mha.cnf: /opt/mysqlRds/mha.cnf not found!
 at /usr/share/perl5/vendor_perl/MHA/ManagerAdminWrapper.pm line 121

检查版本

[root@kmissitdb05 etc]# rpm -qa | grep mha        //通过软件包查看
mha4mysql-manager-0.57-0.el6.noarch
mha4mysql-node-0.57-0.el6.noarch
#或者
[root@kmissitdb05 etc]# masterha_check_status  --version   //通过命令的版本查看
masterha_check_status version 0.57.
#MySQL5.6版本开始支持gtid,mha版本需要大于0.56

查看文件列表

# rpm -qpl <RPM文件路径> 未安装的软件包需要加上p选项
[root@kmissitdb05 6]# rpm -qpl mha4mysql-node-0.57-0.el6.noarch.rpm
/usr/bin/apply_diff_relay_logs
/usr/bin/filter_mysqlbinlog
/usr/bin/purge_relay_logs
/usr/bin/save_binary_logs
/usr/share/man/man1/apply_diff_relay_logs.1.gz
/usr/share/man/man1/filter_mysqlbinlog.1.gz
/usr/share/man/man1/purge_relay_logs.1.gz
/usr/share/man/man1/save_binary_logs.1.gz
/usr/share/perl5/vendor_perl/MHA/BinlogHeaderParser.pm
/usr/share/perl5/vendor_perl/MHA/BinlogManager.pm
/usr/share/perl5/vendor_perl/MHA/BinlogPosFindManager.pm
/usr/share/perl5/vendor_perl/MHA/BinlogPosFinder.pm
/usr/share/perl5/vendor_perl/MHA/BinlogPosFinderElp.pm
/usr/share/perl5/vendor_perl/MHA/BinlogPosFinderXid.pm
/usr/share/perl5/vendor_perl/MHA/NodeConst.pm
/usr/share/perl5/vendor_perl/MHA/NodeUtil.pm
/usr/share/perl5/vendor_perl/MHA/SlaveUtil.pm

查看包信息命令

qpl	Query Package List	查看未安装的 RPM 文件列表	rpm -qpl ./package.rpm 
qpi	Query Package Info	查看未安装的 RPM 包信息	rpm -qpi ./package.rpm
ql	Query List	查看已安装的包文件列表	rpm -ql mha4mysql-node
qi	Query Info	查看已安装的包详细信息	rpm -qi mha4mysql-node
qf	Query File	查看文件所属的 RPM 包	rpm -qf /usr/bin/save_binary_logs
--------------------------------------
yum info mha4mysql-node
yum list installed 列出已经安装的
yum list available 列出未安装的且仓库里面有的
yum search mha  模糊查找某个完整包名
yum provides /usr/bin/save_binary_logs

是否可成为进程

1、排查可执行文件通常是二进制文件或者脚本,比如位于/bin、/sbin、/usr/bin、/usr/sbin等目录下的文件
2、文件 /usr/bin/ls 是一个 ELF 可执行文件,当执行 ls -l 时,它成为一个短暂的进程并立即退出。
   文件 /usr/sbin/nginx 是一个 ELF 可执行文件,当通过 systemctl start nginx 启动时,它成为一个持续    运行的守护进程。
3、判断无守护进程/服务进程:
  守护进程通常会有服务管理文件,比如Systemd的.service文件或者旧的SysVinit的init脚本。判断是否有         systemd 或 init.d 服务配置文件。
  例如:
rpm -qpl keepalived-1.2.15-1.el6.x86_64.rpm
warning: keepalived-1.2.15-1.el6.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID 3c3ebe43: NOKEY
/etc/keepalived
/etc/keepalived/keepalived.conf
/etc/rc.d/init.d/keepalived  ---这个就是守护进程

通过以上,得到node节点的rpm就是脚本的集合,不是守护进程。

posted @ 2025-08-26 16:20  pointarray  阅读(7)  评论(0)    收藏  举报