mha安裝使用手冊
注:目前mha最新的版本代碼已經不放到google code網站了,而是放在github上,最新的版本為0.57,github鏈接如下:
mha manager:https://github.com/yoshinorim/mha4mysql-manager
mha node:https://github.com/yoshinorim/mha4mysql-node
1、安裝
1.1. 安裝環境說明
- 這里只演示一主一從的步驟(即主從所有節點安裝相同的依賴包,管理節點和數據節點的mha包都安裝),一主多從或者兩主一從,兩主多從的步驟類似
- 復制環境
master:10.10.30.169
slave1:10.10.30.146
slave2:10.10.30.155
slave3:10.10.30.140
1.2. 安裝步驟
1.2.1. 安裝依賴包
-
安裝前先把yum源換成epel,否則使用centos源缺少兩個依賴包
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm -
主庫
yum install -y perl-DBD-MySQL
- 從庫或者管理節點
- 如果有專門的管理節點,從庫就只安裝perl-DBD-MySQL
yum install -y perl-DBD-MySQL
- 如果沒有管理節點,那么在所有的主從節點都安裝如下依賴包
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-MIME-Lite perl-Params-Validate
1.2.2. 安裝mha軟件
rpm -Uvh mha4mysql-manager-0.56-0.el6.noarch.rpm mha4mysql-node-0.56-0.el6.noarch.rpm
PS:rpm包中不包含配置文件樣例和故障轉移主庫VIP(master_ip_failover)、在線切換主庫VIP(master_ip_online_change),需要到官網下載源碼包,源碼包中的sample目錄下有
1.2.3. 配置所有節點之間免密碼登錄,包括自己也要能免密碼登錄自己,所以這里配置為只使用同一對密鑰(在主庫上操作即可)
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub root@slave
ssh-copy-id -i .ssh/id_rsa.pub root@master
scp ~/.ssh/id_rsa root@slave:~/.ssh/
- 因為mha運行時需要用到/usr/bin下的兩個mysql命令(貌似路徑寫死了,更改/etc/profile對mha無效),所以建立兩個軟連接
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql
如果發現有這個文件,那么請使用如下命令檢查下是否是低版本的rpm包所裝,如果是,則卸載掉這個包,然后再重新做軟連接
# rpm -qf /usr/bin/mysqlbinlog
mysql-5.1.73-3.el6_5.x86_64
# rpm -e mysql-5.1.73-3.el6_5.x86_64 --nodeps
1.2.4. 從庫設置只讀和關閉自動清理binlog(必須設置,否則做masterha_check_repl這個檢測步驟的時候會不通過)
set global read_only=1;
set global relay_log_purge=0;
1.2.5. 在所有節點上創建如下目錄
# 創建mha的配置文件目錄
mkdir /etc/masterha/app1 -p
# 創建mha的工作目錄
mkdir /var/log/masterha/app1 -p
1.2.6. 創建一個超級管理員以及復制帳號,必須具有遠程連接權限
grant all on *.* to AAA@'%' identified by 'letsg0' with grant option;
grant replication slave on *.* to repl@'%' identified by 'repl';
1.2.7. 配置管理節點配置文件(這里是配置在從庫上)
cat /etc/masterha/app1/app1.conf
[server default]
#mha manager工作目錄
manager_workdir = /var/log/masterha/app1 #管理節點工作目錄,如果管理節點也是數據節點,那么建議設置為與remote_workdir 不同的目錄,如:/tmp
manager_log = /var/log/masterha/app1/app1.log
remote_workdir = /var/log/masterha/app1 #mysql數據節點的工作目錄
# MySQL管理帳號和密碼
user=qogir_env
password=PkC4toqKwgKylN7_2NR1
# 系統ssh用戶
ssh_user=root
# 復制帳號和密碼
repl_user=repl
repl_password= repl
# 監控間隔(秒)
ping_interval=1
manager_log=/var/log/masterha/app1/manager.log
[server1]
hostname=10.10.30.169
master_binlog_dir = /archive/mysqldata1/binlog/
port=3306
[server2]
hostname=10.10.30.146
master_binlog_dir = /archive/mysqldata1/binlog/
candidate_master=1
check_repl_delay=0
port=3306
[server3]
hostname=10.10.30.155
master_binlog_dir = /archive/mysqldata1/binlog/
candidate_master=1
check_repl_delay=0
port=3306
#[binlog1] #如果配置了binlogserver,可以這樣加到配置文件里
#hostname=binlog_host1
PS:關於binlogserver支持的官方原文
Starting from MHA version 0.56, MHA supports new section [binlogN]. In binlog section, you can define mysqlbinlog streaming servers. When MHA does GTID based failover, MHA checks binlog servers, and if binlog servers are ahead of other slaves, MHA applies differential binlog events to the new master before recovery. When MHA does non-GTID based (traditional) failover, MHA ignores binlog servers.
1.2.8. 檢測ssh面密鑰以及復制配置是否正確
# 檢測免密鑰環境需要看到[info] All SSH connection tests passed successfully.提示才算通過
masterha_check_ssh --conf=/etc/masterha/app1/app1.conf
# 檢測復制環境需要看到MySQL Replication Health is OK. 提示才算通過
masterha_check_repl --conf=/etc/masterha/app1/app1.conf
# 檢測通過之后,把這個配置文件復制到其他所有節點
1.2.9. 測試啟動MHA管理節點、檢測管理節點狀態、停止管理節點
nohup masterha_manager --conf=/etc/masterha/app1/app1.conf >> /var/log/masterha/app1/manager.log 2>&1 &
# 此時可以查看日志/var/log/masterha/app1/manager.log 里是否有報錯信息,如果不報錯信息,則繼續往下
# 檢測管理節點狀態,需要看到類似app1 (pid:14913) is running(0:PING_OK), master:10.10.30.169 提示信息才表示無誤
masterha_check_status --conf=/etc/masterha/app1/app1.conf
masterha_stop --conf=/etc/masterha/app1/app1.conf
# 停止管理節點程序之后,檢測下進程是否被關掉
ps aux |grep masterha |grep -v grep
- PS:masterha_check_status 可能會返回的狀態值及其對應的解釋如下表
2、測試
2.1. 現在測試故障轉移,把管理節點啟動起來,然后把主庫停掉,再觀察管理節點的日志輸出
# 管理節點(裝在從庫上)啟動
nohup masterha_manager --conf=/etc/masterha/app1/app1.conf >> /var/log/masterha/app1/manager.log 2>&1 &
# 主庫(10.10.30.169)停止mysql
pkill mysqld
# 查看管理節點日志
vim /var/log/masterha/app1/manager.log
...
Tue Sep 27 17:00:48 2016 - [info] The latest binary log file/position on all slaves is mysql-bin.000118:413749799 #找擁有最新relay log的從庫,這里找到所有從庫最新的位置都處在對應故障主庫的mysql-bin.000118:413749799 這個binlog pos
Tue Sep 27 17:00:48 2016 - [info] Retrieved Gtid Set: d5086143-7f00-11e6-8f06-00163e5b1964:3885658-59476900 #這個是最新從庫的relay log中對應主庫的GTID位置
...
Tue Sep 27 17:00:48 2016 - [info] Searching from candidate_master slaves which have received the latest relay log events.. #開始從備選主庫中查找擁有最新的relay log events的從庫
Tue Sep 27 17:00:48 2016 - [info] New master is 10.10.30.146(10.10.30.146:3306) #10.10.30.146勝出
Tue Sep 27 17:00:48 2016 - [info] Starting master failover.. #開始執行master切換
Tue Sep 27 17:00:48 2016 - [info]
From:
10.10.30.169(10.10.30.169:3306) (current master)
+--10.10.30.146(10.10.30.146:3306)
+--10.10.30.155(10.10.30.155:3306)
To:
10.10.30.146(10.10.30.146:3306) (new master) #10.10.30.146被選舉為新的master,從這里from ...to ...可以看到從from復制架構變成了to 復制架構,故障主庫10.10.30.169被踢出復制組
+--10.10.30.155(10.10.30.155:3306)
Tue Sep 27 17:00:48 2016 - [info] All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.10.30.146', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='xxx'; #這里記錄着新主庫數據的位置,其他從庫就是使用這句切換到新主庫的,你可以看到,開啟了GTID之后,這里change master語句中並沒有binlog pos位置,就跟你手動配置GTID時一樣
Tue Sep 27 17:00:48 2016 - [info] Master Recovery succeeded. File:Pos:Exec_Gtid_Set: mysql-bin.000116, 257595953, 0e9de29e-7f01-11e6-8f08-00163e4c2511:1-5,
d5086143-7f00-11e6-8f06-00163e5b1964:1-59476900 #這里記錄着新主庫的數據對應着故障主庫的GTID位置以及binlog pos
...
Tue Sep 27 17:00:49 2016 - [info] Resetting slave info on the new master.. #等到從庫都切換到新主庫上去之后,新主庫清理之前連接故障主庫的信息
Tue Sep 27 17:00:50 2016 - [info] 10.10.30.146: Resetting slave info succeeded.
Tue Sep 27 17:00:50 2016 - [info] Master failover to 10.10.30.146(10.10.30.146:3306) completed successfully. #看到這里表示主庫切換全部動作完成
2.2. 現在來看看,故障主庫恢復之后,如何加進復制組中
2.2.1. 首先先看看新舊主庫的show master status輸出
old master:
>show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000119
Position: 194
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: d5086143-7f00-11e6-8f06-00163e5b1964:1-59476900
1 row in set (0.00 sec)
new master:
show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000116
Position: 257595953
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 0e9de29e-7f01-11e6-8f08-00163e4c2511:1-5,
d5086143-7f00-11e6-8f06-00163e5b1964:1-59476900 #這個是對應舊主庫的數據GTID
1 row in set (0.00 sec)
# 如果old master的Executed_Gtid_Set大於新主庫中對應UUID哪一個的事物號,那么就表示,新主庫丟了數據了,這個時候你需要自行從舊主庫上提取這部分數據差異出來,然后與應用研發核對這部分數據是否需要補回新主庫中,這個比較蛋疼,補完數據之后,還得把舊主庫的數據干掉重新做成從庫;如果舊主庫的GTID與新主庫對應的UUID那一個GTID相等,那么恭喜你 ,表示數據並沒有丟失。
PS:如果你是使用的傳統復制,那么后續舊主庫恢復之后,有沒有多數據需要去切換日志里邊找 latest binary log file/position記錄,這個就是主庫掛掉之后,其他從庫所擁有的最新的對應舊主庫的binlog pos,然后,使用mysqlbinlog在舊主庫上提取這個位置之后的數據,再人工確認這些數據是否要補到新主庫上
2.2.2. 把舊主庫設置一下read_only
set global read_only=1;
set relay_log_purge=0;
注意:作為從庫加入mha的任何實例,都不能少這個步驟
2.2.3. 然后在mha管理節點的切換日志中,找到change master語句,復制下來,填上密碼就可以執行了
# grep 'CHANGE MASTER TO' /var/log/masterha/app1/manager.log |tail -1
CHANGE MASTER TO MASTER_HOST='10.10.30.155', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='xxx';
2.3. 現在測試下手工在線切換和故障切換功能
2.3.1. 主庫存活在線切換(手工切換需要關閉管理進程)
# masterha_master_switch --conf=/etc/masterha/app1/app1.conf --master_state=alive --new_master_host=10.10.30.169 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=100
# 如果你是跟着文檔流程做到這里,在切換過程中會有三個提示,輸入yes回車即可
* It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 10.10.30.155(10.10.30.155:3306)? (YES/no): yes #這里詢問你是否需要在切換之前在當前主庫上執行FLUSH NO_WRITE_TO_BINLOG TABLES語句
* Starting master switch from 10.10.30.155(10.10.30.155:3306) to 10.10.30.169(10.10.30.169:3306)? (yes/NO): yes #確認是否開始執行切換
* master_ip_online_change_script is not defined. If you do not disable writes on the current master manually, applications keep writing on the current master. Is it ok to proceed? (yes/NO): yes #檢測到master_ip_online_change_script 么有配置,因為到目前為止,並沒有配置VIP,所以會有這個提示,但是要注意,切換的過程中,不要在主庫寫數據
# 切換成功之后,應該看到如下提示:
Thu Sep 29 12:47:37 2016 - [info] Switching master to 10.10.30.169(10.10.30.169:3306) completed successfully.
# 常用參數解釋如下:
--orig_master_is_new_slave 切換時加上此參數是將原 master 變為 slave 節點,如果不加此參數,原來的 master 將不會作為從庫加入到新主庫上,要使用這個參數,配置文件中必須配置repl_password參數,因為新主庫並不知道舊主庫的復制帳號密碼是什么
--running_updates_limit=100,故障切換時,候選master 如果有延遲的話, mha 切換不能成功,加上此參數表示延遲在此時間范圍內都可切換(單位為s),但是切換的時間長短是由recover 時relay 日志的大小決定、
--master_state=alive 告訴mha,當前主庫是活者的,對應的還有一個值是dead,即告訴mha當前主庫死了
--new_master_host 指定新的主庫是誰
--new_master_port 指定新主庫的數據庫端口
2.3.2. 主庫宕機在線切換
# 先把主庫stop掉
# pkill mysqld
# 然后到管理節點上去執行切換命令
# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1/app1.conf --dead_master_host=10.10.30.169 --dead_master_port=3306 --new_master_host=10.10.30.155 --new_master_port=3306 --ignore_last_failover --remove_dead_master_conf
# 如果你是跟着文檔流程做到這里,在切換過程中會有兩個提示,輸入yes回車即可
* Master 10.10.30.169(10.10.30.169:3306) is dead. Proceed? (yes/NO): yes #讓你確認下主庫是否真的死了
* Starting master switch from 10.10.30.169(10.10.30.169:3306) to 10.10.30.155(10.10.30.155:3306)? (yes/NO): yes #讓你確認是否開始執行切換
# 切換成功之后,應該看到類似如下提示
Master failover to 10.10.30.155(10.10.30.155:3306) completed successfully.
# 常用參數解釋
--remove_dead_master_conf 該參數代表當發生主從切換后,老的主庫的ip將會從配置文件中移除。默認情況下,主庫切換之后並不會修改配置文件
--manger_log 日志存放位置
--ignore_last_failover 在缺省情況下,如果MHA檢測到連續發生宕機,且兩次宕機間隔不足8小時的話,則不會進行Failover,之所以這樣限制是為了避免ping-pong效應。該參數代表忽略上次MHA觸發切換產生的文件,默認情況下,MHA發生切換后會在日志目錄,也就是上面我設置的/data產生app1.failover.complete文件,下次再次切換的時候如果發現該目錄下存在該文件將不允許觸發切換,除非在第一次切換后收到刪除該文件,為了方便,這里設置為--ignore_last_failover,另外,新版本0.56可以不使用這個參數,也不需要專門去刪除app1.failover.complete文件
--dead_master_host 指定死掉的主庫的IP
--dead_master_port 指定死掉的主庫的數據庫端口
# 查看app1.conf文件,會發現死掉的主庫配置被刪掉了
grep '10.10.30.169' /etc/masterha/app1/app1.conf
# 在線切換需要滿足如下條件
* 所有從庫的IO和SQL線程必須為運行狀態
* 所有從庫的Seconds_Behind_Master 的值必須小於--running_updates_limit 參數指定的數值
* 在主庫上,show processlist出來的更新(個人覺得這里應該是指的對數據有變更操作的任何請求,而不僅僅是update)請求不能有超過--running_updates_limit 參數指定的數值的時間
2.3.3. 其他參數
--interactive=(0|1) 如果你想非交互式的執行切換,那么設置這個參數為0,默認是1,要使用該選項,你需要確定主庫的狀態是dead還是online,或者其他程序調用masterha_master_switch切換命令時使用
--skip_change_master 0.56版本新增功能, 默認情況下,主庫切換時,其他從庫會change到新主庫上,這個參數可以在從庫數據恢復之后,跳過change 到新主庫以及跳過start slave,這樣你就可以手動到從庫上去再次確認數據有沒有恢復成功
--skip_disable_read_only 0.56版本新增功能,默認情況下,主庫切換到新主庫時,新主庫會執行set global read_only=0; 打開新主庫可讀寫,加上這個參數之后,跳過設置read_only=0語句
--wait_until_gtid_in_sync(0|1) 0.56版本新增的功能,默認為1,表示發生故障轉移時,MHA會等待其他從庫追趕上新主庫的GTID位置,如果設置為0,則不會等待
--ignore_binlog_server_error 0.56版本新增功能,表示在故障轉移時,跳過任何binlog server的錯誤
--skip_lock_all_tables 默認情況下,在執行主庫切換的時候,舊主庫會執行flush table with read lock語句來確保主庫停止寫,但是執行flush table with read lock是一個昂貴的操作,如果你能夠人工判斷並確認主庫沒有寫操作,那么可以使用這個選項來跳過執行這個語句。master_ip_online_change_script 這個參數並殺掉所有的客戶端連接
2.3.4. 現在,把VIP功能加進來,然后再重復前面的手工切換步驟,看看切換是否正常
VIP切換功能依賴master_ip_failover和master_ip_online_change兩個腳本,master_ip_failover是故障切換VIP的腳本,master_ip_online_change是在線切換VIP的腳本,這兩個腳本默認在rpm包里是沒有的,需要到源碼包的sample/scripts目錄下獲取,把scripts目錄放到目錄/etc/masterha/下
vim /etc/masterha/app1/app1.conf #把下面一段配置加到/etc/masterha/app1/app1.conf 里(注:線面一段參數除故障轉移,還包括發生切換的通知腳本,以及使用其他網絡路徑二次檢測確認主庫是否有故障的腳本,以及在檢測到主庫故障時,關閉主庫的腳本)
master_ip_failover_script=/etc/masterha/scripts/master_ip_failover #發生故障的時候,切換VIP的腳本,這個腳本不完整,需要自己修改,故障切換必須配置
# shutdown_script=/etc/masterha/scripts/power_manager #在發生故障切換的時候,關閉主庫的腳本,這個腳本要自己寫,可不配置
#report_script=/etc/masterha/scripts/send_report #在發生故障切換的時候,發送郵件的腳本,這個腳本不完整,需要自己修改,可不配置
master_ip_online_change_script=/etc/masterha/scripts/master_ip_online_change #在線切換VIP的腳本,這個腳本不完整,需要自己修改,在線切換必須配置
# secondary_check_script= /usr/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=10.10.30.155 --master_port=3306 # 一旦MHA到server02的監控之間出現問題,MHA Manager將會嘗試從server03登錄到server02,可不配置
3、mha組件命令使用詳解
- 注意,這里講到的都是日常維護和使用中需要手工調用的組件,還有一些是mha自動調用的組件在這里不做介紹,有星期可以自己去看命令幫助
3.1. masterha_manager命令只能監控主庫的可用性,對於正在使用的復制架構,如果有從庫的SQL線程或者IO線程意外終止,或者說有從庫添加/刪除/重啟/停止,MHA監控是無法感知的(如果你對從庫結構做了什么調整,那么請重啟MHA監控程序),這個命令並不能發現(但是,這個命令在啟動的時候,會調用masterha_check_repl來檢查復制和ssh連通性,檢查過了才會啟動成功,否則無法啟動成功),可以定期使用masterha_check_repl --conf=/etc/app1.cnf來檢測一下,這個命令會檢測所有的節點的復制架構是否正常,並及時發出警告信息,該工具可以發現如下錯誤信息:
- MHA不能監控或者MHA不能做故障轉移的錯誤(如:復制過濾規則不同,有節點的SQL線程錯誤停止了,你的配置文件中有配置兩個或者更多的master)
- 有節點的IO線程停止了
- 節點SQL線程正常停止
- 有節點的復制延遲大於N秒,使用參數--seconds_behind_master=(seconds)指定延遲大於多少就發出警告,默認是30s
默認情況下,這個檢測腳本也會調用masterha_check_ssh檢測ssh的連通性,如果你確定ssh是可以的,不需要檢測,那么就使用這個參數跳過ssh的檢測--skip_check_ssh
PS:MHA故障轉移過程中的一些判斷邏輯、調用腳本的順序等
- 如果MHA在主庫掛掉之后,做切換的時候,發現其他的從庫連着不同的主庫,即有的從庫連接着的不是死掉那個主庫,那么MHA監控程序報錯並停止,如果你確定你某個從庫需要連接其他的主庫,那么可以在主機配置段落里加上參數 ignore_fail來忽略這個錯誤,讓MHA繼續做切換
- 如果MHA最近一次故障轉移失敗,或者最近一次故障轉移時間太近,那么MHA監控程序將拒絕啟動,你可以使用選項 ignore_last_failover and wait_on_failover_error arguments來啟動監控程序
- 如果你在配置文件中配置了master_ip_failover_script and/or shutdown_script,那么MHA監控程序會調用這些腳本關閉死掉的主庫電源,以避免腦裂發生
- 如果主庫操作系統直接掛了,那么在MHA提升新主庫的時候,會把新主庫對應舊主庫的binlog pos位置記錄在切換日志里,等到舊主庫恢復之后,你可以根據這個位置到故障主庫上去找出丟失那部分,然后自行決定要不要把這部分補到新主庫上去。
- 提升新主庫的依據: 基於MHA配置文件和當前MySQL的設置,如果你想指定備用主庫,可以在配置文件中對應的主機配置段落下用candidate_master=1參數指明,如果你不想某個從庫作為備用主庫,那么可以在配置文件中對應的主機配置段落下用no_master=1參數禁止這個從庫被提升為新主庫。
- 根據最新的relay logs來識別出latest slave,根據IO線程讀取的故障主庫的位置做比較
- 選舉出latest slave之后,就需要把它提升為新的主庫,首先生成差異的binlog/relay log,然后應用到這個新主庫上,如果這個過程發生任何錯誤,那么MHA將終止后續的所有過程,包括其他從庫的數據恢復操作
- 使用master_ip_failover_script腳本激活新主庫,比如激活VIP,或者特權用戶什么的
- 並行恢復其他slave,把差異binlog/relay log冰箱應用到其他從庫上面,change master到新主庫上,在這個階段,如果有從庫恢復數據失敗,MHA不會終止這個恢復過程,會繼續恢復,只是恢復失敗的從庫不能夠從新主庫上同步數據,而恢復成功的則繼續從新主庫上同步數據。
- 如果你在配置文件中定義了report_script參數,那么MHA可以調用它發送郵件,在新的主庫上關閉計划備份,升級內部管理工具的狀態等
- MHA讀取配置文件中的信息,識別當前主庫(MHA不會自己幫你創建復制環境,MHA只能在一個搭建好的復制環境下幫你監控主庫)
- MHA監控程序啟動的時候,會檢查所有從庫的IO和SQL線程是否在運行,所有從庫的Seconds_Behind_Master 是否大於2S(可以使用參數--running_updates_limit來改變這個值),在master上,show processlist輸出中,有沒有更新語句超過2S的
- 默認情況下,MHA切換的時候,新的主庫是自動識別的,如果你想要切換到某個指定的SLAVE上,可以使用選項--new_master_host指定
- 如果你在配置文件中設置了 master_ip_online_change_script 參數,那么在MHA在線切換的過程中,就可以優雅地阻塞舊主庫上的寫請求(移除寫請求的用戶,並執行set global read_only=1;在舊主庫上執行flush table with read lock語句獲取全局讀鎖阻塞所有的寫請求,如果你不想要加全局讀鎖這個步驟,可以使用參數--skip_lock_all_tables來跳過)
- 所有從庫上使用MASTER_LOG_POS() 函數來追趕主庫
- 允許新主庫寫:先在新主庫上執行show master status語句把binlog file和binlog pos查出來,然后,如果你在配置文件中有定義 master_ip_online_change_script參數,那么MHA將調用這個腳本來創建寫用戶,並執行set global read_only=0;
- 在其他從庫上並行執行change master到新主庫並start slave開始從新主庫同步數據
3.2. masterha_stop
這個命令只是停止管理節點的監控程序,並不會停止MySQL,並且,使用這個命令來停止管理節點程序的時候,如果發現管理節點程序正在進行故障轉移,則不會停止管理節點,會直接退出停止,這樣做是為了避免出現在故障轉移過程中出現不一致的復制配置信息,如果你是手動在shell命令行敲的kill pid方式殺掉管理節點的程序,請確保管理節點沒有處於正在進行故障轉移的階段。
3.3. masterha_conf_host
有時候,你可能想要從配置文件中添加或者刪除一個主機記錄,比如你新安裝了一個從庫,又不想手動去編輯配置文件,那么,就可以使用這個命令來添加,命令如下:
masterha_conf_host --command=add --conf=/etc/conf/masterha/app1.cnf --hostname=db101
配置文件添加結果如下:
[server_db101]
hostname=db101
從結果上可以看到,hostname選項指定的db101被配置到了兩個地方,[server_db101]為段落標簽,如果你沒有顯式指定這個,就會使用server_$hostname的方式生成
如果你想手動指定段落標簽(使用--block選項指定),且還想添加額外的一些參數(使用--params選項來指定,指定的內容用引號引起來,使用分號作為間隔),可以使用如下命令:
masterha_conf_host --command=add --conf=/etc/conf/masterha/app1.cnf --hostname=db101 --block=server100 --params="no_master=1;ignore_fail=1"
配置文件中添加結果如下:
[server100]
hostname=db101
no_master=1
ignore_fail=1
如果你想刪除一個主機記錄,可以使用如下命令(指定--block選項,不需要帶這個主機的具體參數):
masterha_conf_host --command=delete --conf=/etc/conf/masterha/app1.cnf --block=server100
這樣就可以把主機server100的整個段落配置從配置文件中刪掉
參數解釋:
--command=delete|add #從一個配置文件中添加/刪除一個主機記錄
--block #顯式指定配置文件中,主機配置文件的段落標記
--conf #指定本地配置文件路徑
--hostname #指定添加記錄的主機名或者IP
--params #指定參數列表,使用分號作為參數間隔,所有參數使用引號引起來
3.4. secondary_check_script
MHA在連續三次檢測到主庫連接失敗之后,如果配置文件中配置了secondary_check_script腳本,那么會調用這個腳本對主庫進行再次確認主庫是否真的死掉了
4、其他
4.1. 后台或daemon運行mha manager
- 默認情況下,mha manager程序運行在前台,你可以像下面這樣把程序運行在后台:
nohup masterha_manager --conf=/etc/app1.cnf < /dev/null > /var/log/masterha/app1/app1.log 2>&1 &
- 使用daemontools工具把mha manager作為一個daemon運行
當前mha manager不作為一個daemon運行,如果故障轉移成功或者說master進程被意外地殺死,這個manager程序將停止工作,可以使用外部的daemon程序把manager程序作為daemon運行,具體配置過程如下(針對redhat發行版的安裝過程): - 安裝daemontools
yum install daemontools -y
- 在/service/masterha(app_name)/run目錄下創建運行文件
mkdir /service/masterha_app1
cat /service/masterha_app1/run
#!/bin/sh
exec masterha_manager --conf=/etc/app1.cnf --wait_on_monitor_error=60 --wait_on_failover_error=60 >> /var/log/masterha/app1/app1.log 2>&1
chmod 755 /service/masterha_app1/run
- 通過如下命令來停止或重啟daemontool 的監控命令
停止監控:
svc -d /service/masterha_app1
開始監控:
svc -u /service/masterha_app1
4.2. 運行多個mha manager程序
如果你需要在同一個mha manager服務器上監控對多主從架構,那么只需要創建一個新的配置文件,然后使用命令masterha_manager 跟上新的配置文件啟動監控程序即可,如下:
masterha_manager --conf=/etc/conf/masterha/app1.cnf
masterha_manager --conf=/etc/conf/masterha/app2.cnf
此時,如果你在兩對主從配置文件中有一些相同的參數,那么推薦把這些相同的參數放到全局配置文件中。
4.3. 與集群軟件結合
如果你在master上使用了VIP,那么可能你已經使用了集群軟件了,如果你熟悉目前的集群管理工具,那么你可能也需要使用這個集群工具來管理VIP,而不是什么事情都在MHA里來做,MHA只使用在非交互式的故障轉移中,所以可以使用集群軟件結合MHA來做master的故障轉移,讓集群軟件來管理VIP。MHA重點做提升一個新主庫以及修復與從庫的數據一致性的工作。
以下是一個heartbeat 軟件節點配置示例:
/etc/ha.d/haresources on host2
host2 failover_start IPaddr::192.168.0.3
- 故障轉移腳本示例
start)
masterha_master_switch --master_state=dead --interactive=0 --wait_on_failover_error=0 --dead_master_host=host1 --new_master_host=host2
exit
stop)
do nothing
- application配置文件示例
[server1]
hostname=host1
candidate_master=1
[server2]
hostname=host2
candidate_master=1
[server3]
hostname=host3
no_master=1
因為數據文件不共享,數據資源不需要被集群軟件或者DRDB管理,為此,集群管理軟件只是調用masterha_master_switch 腳本和接管VIP,當然,你也可以自己寫一個腳本來做這個事情。
4.4. FAQ內容摘錄
4.4.1. FAQ
- 支持mysql5.0及其更高的版本,支持5.6+的系統表復制信息(relay log pos系統表)
- 支持所有的linux發行版,也可以工作在UNIX平台(但沒有經過測試),不支持WINDOWS
- master的binlog file和pos在slave的relay log中有寫,所以從slave的relay log中MHA可以精准地識別、解析出對應主庫的位置
- MHA在做故障轉移的時候,會判斷所有從庫是否存活,如果不是,那么MHA將拒絕故障轉移操作(從庫不是alive的情況包括:從庫無法通過連接mysql時;SQL線程因為報錯而停止時;不能通過ssh連接從庫時,因為要獲取差異日志)
- 在master執行load data加載大量數據時,且binlog格式是statement,那么,如果主庫此時crash了,從庫在恢復時可能會失敗,基於語句級別的復制在Mysql中不推薦,所以最好不要使用。
- MHA需要使用OS系統帳號來讀取MySQL的binlog和relay log,如果能提供OS系統帳號權限,那么可以在雲上使用MHA,MHA不依賴VIP,所以就算供應商不提供額外的VIP也可以使用MHA
- 在以下三種情況下,MHA也不會進行故障轉移操作
- 所有節點之間的復制過濾規則不相同
- 上一次故障轉移失敗,故障轉移失敗的日志文件會寫在工作目錄下,你需要移除它並手動重啟故障轉移
- 上一次故障轉移的時間離現在太近(在多少時間之內),默認是8個小時,可以通過參數 --last_failover_minute=(minute))來設置這個時間,在這個場景下,MHA不進行故障轉移是因為高頻轉移失敗,MHA判定通過故障轉移並不能解決這個問題
- 哪些host不會被選擇為新主庫?
- 在配置文件中設置了no_master=1的
- log-bin功能沒有打開的
- 所有slave的mysql版本不能低於5.0
- SQL線程復制顯著延遲的,如果Relay_Master_Log_File 落后與Master_Log_File ,或者說Exec_Master_Log_Pos 落后於Read_Master_Log_Pos 大於100,000,000,MHA就判定目標slave已經顯著延遲
- 哪些host會被選擇為新主庫?
- 如果在配置文件中設置了candidate_master=1的,將被優先提升為新主庫,然后再在這些優先的slave中看看是否有接收到最新的binlog,如果有多個slave都接收到了最新的binlog(即被判定為latest slave),在這種情況下,MHA將按照在配置文件中配置的順序來選擇最終誰為新主庫
- 如果在配置文件中,沒有任何主機設置candidate_master=1,那么接受到最新的binlog 的slave被選擇為新主庫,如果多個從庫都接收到了最新的binlog,那么就按照配置文件中的順序來選擇新主庫。
- 如果接收到最新的binlog的slave中,沒有可以作為新主庫的,那么將從non-latest slave(即並不是最新binlog的slave)中選擇,如果non-latest slave也有多個,也將按照配置文件中的順序來選擇新主庫
- 如果在配置文件中設置了 latest_priority=0,那么是否是latest slave(是否接收到最新的binlog)就沒有關系了,所有的slave都參與選擇新主庫,那么你就可以在配置文件中使用配置順序來控制主機被提升為新主庫的優先級
- 如何做mha manager自身的高可用?當前針對同一個master的監控,MHA還不支持多個mha manager,所以,如果mha manager自己掛了,那么自動故障轉移就沒有辦法進行,這個是比較嚴峻的問題,但是你也許又想要mha manager自身盡可能地實現高可用,那么推薦通過使用mha manager的HA active/standby方案來實現
- 當添加/移除MySQL實例的時候,需要做什么?需要手動更新application配置文件,然后重啟mha manager,如果你不想手動去修改配置文件,你可以使用masterha_conf_host工具
- 怎么在配置文件中設置master?你不需要在配置文件中去設置master,MHA連接配置文件中所有的主機並自動判斷當前的master是誰
- 執行故障轉移的時候調用purge_relay_logs會不會把relay log給清理掉?這種情況永遠不會發生,因為在故障轉移開始時,就會先在所有從庫上加咨詢鎖,而這個清理工具也需要獲得相同的鎖才能執行清理操作。所以,在故障轉移的時候,這個命令是無法獲得需要的鎖,所以就無法執行。
4.5.2. 常見錯誤以及修復方法
- mha node包在mysql實例上沒有安裝,以下示例中,host2沒有安裝mha node的包,報如下錯誤:
...
Sat Jul 2 13:24:25 2011 - [info] Checking MHA Node version..
Sat Jul 2 13:24:25 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/ManagerUtil.pm, ln114] Got error when getting node version. Error:
Sat Jul 2 13:24:25 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/ManagerUtil.pm, ln115]
bash: apply_diff_relay_logs: command not found
Sat Jul 2 13:24:25 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/ManagerUtil.pm, ln130] node version on host2 not found! Maybe MHA Node package is not installed?
at /usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm line 276
Sat Jul 2 13:24:25 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln316] Error happend while checking configurations. Died at /usr/lib/perl5/site_perl/5.8.5/MHA/ManagerUtil.pm line 131.
Sat Jul 2 13:24:25 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln397] Error happened while monitoring servers.
Sat Jul 2 13:24:25 2011 - [info] Got exit code 1 (Not master dead).
Died at /usr/bin/masterha_manager line 59.
- 找不到master的binlog在哪里,在下面的示例中,沒有使用master_binlog_dir 參數在配置文件中指定master的binlog存放路徑,如果你的master的路徑不是rpm發行包下的標准路徑( /var/lib/mysql,/var/log/mysql),就會報如下錯誤:
Sat Jul 3 20:03:40 2011 - [info] Checking MHA Node version..
Sat Jul 3 20:03:41 2011 - [info] Version check ok.
Sat Jul 3 20:03:41 2011 - [info] Checking SSH publickey authentication and checking recovery script configurations on the current master..
Sat Jul 3 20:03:41 2011 - [info] Executing command: save_binary_logs --command=test --start_file=binlog.000002 --start_pos=4 --binlog_dir=/var/lib/mysql,/var/log/mysql --output_file=/var/tmp/save_binary_logs_test --manager_version=0.50
Sat Jul 3 20:03:41 2011 - [info] Connecting to root@hostx(192.168.0.1)..
Failed to save binary log: Binlog not found from /var/lib/mysql,/var/log/mysql!
at /usr/bin/save_binary_logs line 95
eval {...} called at /usr/bin/save_binary_logs line 59
main::main() called at /usr/bin/save_binary_logs line 55
Sat Jul 3 20:03:41 2011 - [error][/usr/lib/perl5/site_perl/5.8.8/MHA/MasterMonitor.pm, ln94] Master setting check failed!
Sat Jul 3 20:03:41 2011 - [error][/usr/lib/perl5/site_perl/5.8.8/MHA/MasterMonitor.pm, ln296] Master configuration failed.
Sat Jul 3 20:03:41 2011 - [error][/usr/lib/perl5/site_perl/5.8.8/MHA/MasterMonitor.pm, ln316] Error happend on checking configurations. at /usr/bin/masterha_manager line 50
- 沒有權限讀取binlog/relay log的目錄,如果你在配置文件中指定的ssh_user用戶沒有權限訪問binlgo/relay log的目錄,就會報如下錯誤(建議使用高權限的用戶,如root用戶作為SSH連接用戶):
...
Sat Jul 2 13:27:21 2011 - [info] Checking SSH publickey authentication and checking recovery script configurations on the current master..
Sat Jul 2 13:27:21 2011 - [info] Executing command: save_binary_logs --command=test --start_file=mysqld-bin.000001 --start_pos=4 --binlog_dir=/var/lib/mysql --output_file=/var/log/masterha/save_binary_logs_test --manager_version=0.50
Sat Jul 2 13:27:21 2011 - [info] Connecting to app@host1(host1)..
Failed to save binary log: Permission denied:/var/lib/mysql/mysqld-bin.000001
at /usr/bin/save_binary_logs line 96
Sat Jul 2 13:27:21 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln94] Master setting check failed!
Sat Jul 2 13:27:21 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln296] Master configuration failed.
Sat Jul 2 13:27:21 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln316] Error happend while checking configurations. at /usr/bin/masterha_manager line 50
Sat Jul 2 13:27:21 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln397] Error happened while monitoring servers.
Sat Jul 2 13:27:21 2011 - [info] Got exit code 1 (Not master dead).
Died at /usr/bin/masterha_manager line 59.
- 使用了多主復制(默認情況下,所有的從庫需要配置成從相同的主庫上復制),MHA不支持,就會報如下錯誤:
...
Sat Jul 2 13:23:14 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/ServerManager.pm, ln522] FATAL: Replication configuration error. All slaves should replicate from the same master.
Sat Jul 2 13:23:14 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/ServerManager.pm, ln1066] MySQL master is not correctly configured. Check master/slave settings
Sat Jul 2 13:23:14 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln316] Error happend while checking configurations. at /usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm line 243
Sat Jul 2 13:23:14 2011 - [error][/usr/lib/perl5/site_perl/5.8.5/MHA/MasterMonitor.pm, ln397] Error happened while monitoring servers.
Sat Jul 2 13:23:14 2011 - [info] Got exit code 1 (Not master dead).
Died at /usr/bin/masterha_manager line 59.
4.6. MHA內部如何工作
4.6.1. 如何確定從中繼日志的什么位置開始應用?
-
很久以前,MHA使用mysqlbinlog來識別relay log的位置,現在,MHA不使用mysqlbinlog,而是使用解析binlog的頭部信息的方法來識別位置
-
使用解析自己binlog頭部代替mysqlbinlog解析的原因是,mysqlbinlog解析的方法有些問題,最大的原因是因為mysqlbinlog沒有一個選項使他只打印binlog的頭部信息,它總是打印binlog的內容主體部分
-
要識別relay log的位置,所有必要的信息(binlog event type,server id,event length,end log pos)都保存在binlog的頭部信息當中,所以不需要去解析binlog的內容主體部分,mysqlbinlog不僅增加了讀取binlog數據的性能開銷,而且我們還需要關心某些類型的SQL語句,因為基於SQL語句的binlog在內容主體里邊可能包含了一些位置信息。
-
快速查找relay log的位置
-
假如目標master(需要恢復的slave)的log file:pos is mysqld-bin.000001:504810023,latest master的log file:pos is mysqld-bin.000001:504810689,latest relay log的og file is mysqld-relay-bin.000001以及文件大小大於500M,但是這兩個位置信息之差僅僅只占用666個字節,如果MHA解析整個relay log,就是500M的大小,需要耗費比較長的時間,也就是說,需要耗費比較長的時間來恢復數據,造成長時間的down機,所以,MHA並不總是從開頭掃描relay log,也會從差異的位置開始掃描,基於如下掃描規則:
$latest_mlf = Master_Log_File on the latest slave
$target_mlf = Master_Log_File on the recovery target slave
$latest_rmlp = Read_Master_Log_Pos on the latest slave
$target_rmlp = Read_Master_Log_Pos on the recovery target slave
$offset = $latest_rmlp - $target_rmlp
$filesize = File size of the latest relay log file on the latest slave
如果$latest_mlf等於$target_mlf and $filesize > $offset,and 如果binlog event可以從$filesize - $offset這個位置讀取到(其實這個相當於從relay log的末尾倒推),MHA就決定開始從lasest slave的relay log中的($filesize - $offset) 這個位置開始恢復,這樣就避免了掃描巨大的relay log文件,提高掃描的速度。
4.6.2. 怎樣生成應用到目標slave的SQL語句?
-
MHA處理這部分邏輯算法現在是(三個步驟生成一個二進制日志文件,文件名默認為/var/tmp/aggregate.binlog):
-
把目標slave(需要恢復數據的slave)的從exec pos到read pos位置的binlog的內容從relay log中提取出來(這里沒有經過mysqlbinlog解析,而是直接讀的原始的二進制格式日志),生成/var/tmp/aggregate.binlog文件
-
把從目標slave的read pos到最新的latest slave的read pos之間的binlog內容從latest slave的relay log中提取出來,去掉每一個relay log的Format_description_event(一個日志文件只能有一個FDE,所以第二個步驟要去掉FDE),並合並到/var/tmp/aggregate.binlog里
-
把從最新的latest slave的read pos到master的最后一個日志尾之間binlog的內容提取出來,去掉每一個binlog的FDE,並合並到/var/tmp/aggregate.binlog里
-
執行mysqlbinlog命令來解析這個合成的二進制日志文件,並通過mysql命令應用到目標slave中
-
PS:加一點自己的理解,縱觀MHA整個故障轉移過程來說,上面第三步提取master的日志其實是在補償新主庫的階段就先提取過了,然后放到了mha manager上,在恢復從庫的階段,只是在第三步的時候,把這個差異日志從mha manager上復制過來,並合並到/var/tmp/aggregate.binlog里(沒有去研究源碼,只是個人的理解),要注意的是,前面三個提取二進制日志的步驟順序不能亂,亂了數據就亂了
-
邏輯變更的原因如下:
-
為了支持基於row格式的binlog event:當前mysqlbinlog不能夠准確地打印一個有效的SQL語句,除非基於row格式的整個event都寫在了一個log file里,例如:如果部分event(TABLE_MAP_EVENT event) 寫在了mysqld-relay-bin.000001 ,剩下一部分event(WRITE_ROWS events) 寫在了 mysqld-relay-bin.000002,那么mysqlbinlog打印一個有效的基於row格式的event,所以原始的方案(合並多個mysqlbinlgo命令的輸出)在基於row格式時並不總是能正常工作, 新的方案適用於語句和row格式,因為mysqlbinlog需要解析的對象是經過合並的單個log file。
-
mysqlbinlog隱式地在輸出內容的尾部添加rollback語句,有些時候在每一個binlog file的開頭也存在,這樣rollback語句需要修剪,以避免局部事務回滾,解析所有mysqlbinlog輸出、替換目標rollback語句以及等效BINLOG語句,但是解析所有的輸出會增加開銷,新的方案只需要解析單個日志,只返回一次rollback語句,不需要添加中間事務。所以,MHA創建單個大的binlog file來應用到每一個目標從庫,當需要合並多個relay/binary log的時候,MHA裁剪掉除了第一個日志之外其他日志的format description events,裁剪這個的原因是mysqlbinlog解析這個日志的時候,多余的format description events可能會產生一些不必要的rollback語句
5、mha的配置文件參數詳解
- 配置參數詳解:
作用域范圍解釋: Local Scope 表示可以設置在單個app配置文件中的[server_xx]塊標記下邊的參數;App Scope表示可以針對單個app內所有的master和slave設置,可以設置在單個app配置文件中的[server_default]塊標記下邊;Global Scope表示全局參數,可以設置在全局配置文件中
-
以下是配置文件中具體每個配置參數的解釋:
-
hostname:目標實例的主機名或者IP地址,這個參數是強制的,只能配置在app配置文件的[server_xxx]段落標記下
-
ip:目標實例的ip地址,默認從hostname獲取,MHA內部管理節點與數據節點之間的mysql和ssh通過這個IP連接,正常情況下你不需要配置這個參數,因為MHA會自動解析Hostname獲得
-
port:目標實例的端口,默認是3306,MHA使用mysql server的IP和port連接
-
ssh_host:從0.53版本開始支持,默認情況下和hostname參數相同,當你使用了VLAN隔離的時候,比如為了安全,把ssh網段和訪問數據庫實例的網段分開使用兩個不同的IP,那么就需要單獨配置這個參數
-
ssh_ip:從0.53版本開始支持,默認情況下與ssh_host相同
-
ssh_port:從0.53版本開始支持,目標數據庫的ssh端口,默認是22
-
ssh_connection_timeout:從0.54版本開始支持,默認是5秒,增加這個參數之前這個超時時間是寫死在代碼里的
-
ssh_options:從0.53版本開始支持,額外的ssh命令行選項
-
candidate_master:從不同的從庫服務器中,提升一個可靠的機器為新主庫,(比如:RAID 10比RAID0的從庫更可靠),可以通過在配置文件中對應的從庫服務器的配置段下添加candidate_master=1來提升這個從庫被提升為新主庫的優先級(這個從庫要開始binlog,以及沒有顯著的復制延遲,如果不滿足這兩個條件,也並不會在主庫掛掉的時候成為新主庫,所以,這個參數只是提升了優先級,並不是說指定了這個參數就一定會成為新主庫)
-
no_master:通過在目標服務器的配置段落設置no_master=1,它永遠也不會變為新主庫,用於配置在不想用於接管主庫故障的從庫上,如:只是一個binlog server,或者硬件配置比較差的從庫上,或者這個從庫只是一個遠程災備的從庫,但是,要注意,不能把所有的從庫都配置這個參數,這樣MHA檢測到沒有可用備主的時候,會中斷故障轉移操作
-
ignore_fail:默認情況下,MHA在做故障轉移的時候,會去檢測所有的server,如果發現有任何的從庫有問題(比如不能通過SSH檢測主機或者mysql的存活,或者說有SQL線程復制錯誤等)就不會進行故障轉移操作,但是,有時候可能需要在特定從庫有故障的情況下,仍然繼續進行故障轉移,就可以使用這個參數指定它。默認是0,需要設置時在對應服務器的配置段下添加ignore_fail=1
-
skip_init_ssh_check:監控程序啟動的時候,跳過SSH連接檢測 * skip_reset_slave:0.56開始支持,master故障轉移之后,跳過執行reset slave all語句 * user:目標mysql實例的管理帳號,盡量是root用戶,因為運行所有的管理命令(如:stop slave,change master,reset slave)需要使用,默認是root
-
password:user參數指定的用戶的密碼,默認為空
-
repl_user:在所有slave上執行change master的復制用戶名,這個用戶最好是在主庫上擁有replication slave權限
-
repl_password:repl_user參數指定的用戶的密碼,默認情況下,是當前復制帳號的密碼,如果你運行了online master switch腳本且使用了--orig_master_is_new_slave做在線切換,當前主庫作為了從庫加入新主庫,此時,如果你沒有設置repl_password來指定復制帳號的密碼,當前主庫作為從庫加入新主庫的時候會在change master的時候失敗,因為默認情況下這個密碼是空的,MHA做切換的時候,其他所有作為從庫加入新主庫時,都需要使用這個密碼
-
disable_log_bin:如果設置這個參數,當應用差異日志到從庫時,slave不生成binlog寫入,內部通過mysqlbinlog命令的--disable-log-bin選項實現
-
master_pid_file:設置master的pid,在運行多實例的環境下,你可能需要用到這個參數來指定master的pid,參考shutdown_script參數詳解
-
ssh_user:訪問MHA manger和MHA mysql節點的OS系統帳號,需要使用它來遠程執行各種各樣的管理mysql節點的命令(從manager到mysql),從latest slave拷貝差異日志到其他從庫上(從mysql到mysql),該用戶必須要能夠沒有任何交互地連接到服務器,通常使用ssh key認證,默認情況下,這個用戶是manager所在的OS系統用戶。
-
remote_workdir:每一個MHA node(指的是mysql server節點)生成日志文件的工作路徑,這個路徑是絕對路徑,如果該路徑目錄不存在,則會自動創建,如果沒有權限訪問這個路徑,那么MHA將終止后續過程,另外,你需要關心一下這個路徑下的文件系統是否有足夠的磁盤空間,默認值是/var/tmp
-
master_binlog_dir:在master上生成binlog的絕對路徑,這個參數用在master掛了,但是ssh還可達的時候,從主庫的這個路徑下讀取和復制必須的binlog events,這個參數是必須的,因為master的mysqld掛掉之后,沒有辦法自動識別master的binlog存放目錄。默認情況下,master_binlog_dir的值是/var/lib/mysql,/var/log/mysql,/var/lib/mysql目錄是大多數mysql分支默認的binlog輸出目錄,而 /var/log/mysql是ubuntu包的默認binlog輸出目錄,這個參數可以設置多個值,用逗號隔開
-
log_level:manager記錄日志的等級,默認以及大多數場景下都是info級別,可以設置的值為debug/info/warning/error
-
manager_workdir:mha manager生成的相關狀態文件的絕對路徑,如果沒有設置,則默認使用/var/tmp
-
client_bindir: 如果mysql命令工具是安裝在非標准路徑下,那么使用這個參數指定絕對路徑
-
client_libdir:如果mysql的庫文件是安裝在非標准路徑下,那么使用這個參數指定據對路徑
-
manager_log:mha manager生成的日志據對路徑,如果沒有設置,mha manager將打印在標准輸出,標准錯誤輸出上,如:當mha manager執行故障轉移的時候,這些信息就會打印
-
check_repl_delay:默認情況下,如果從庫落后主庫100M的relay logs,MHA不會選擇這個從庫作為新主庫,因為它會增加恢復的時間,設置這個參數為0,MHA在選擇新主庫的時候,則忽略復制延遲,這個選項用在你使用candidate_master=1 明確指定需要哪個從庫作為新主庫的時候使用。
-
check_repl_filter:默認情況下,如果master和slave相互之間有任何不同的binlog復制過濾規則,MHA將打印錯誤日志並拒絕啟動監控程序或者拒絕故障轉移操作,這是為了避免意外出現類似Table not exists這樣的錯誤,如果你100%確定不同的復制過濾規則不會出現恢復問題,那么就設置check_repl_filter = 0,此時MHA在應用差異日志的時候就不會去檢測復制過濾規則,但是你可能會碰到Table not exists這樣的錯誤,使用這個參數要非常小心
-
latest_priority:默認情況下,latest slave(收到最新的binlog的slave),優先作為新主庫,如果你想控制這個優先級順序,可以通過 latest_priority=0,此時,就會按照配置文件中配置的順序來選擇新主庫(如 host2->host3->host4)。
-
multi_tier_slave:從0.52版本開始,支持多個主庫的復制架構,默認情況下,在配置文件中不支持三個或更多層級的復制架構,例如:host2從host1復制,host3從host2復制,默認情況下,是不允許host1,2,3同時可寫的。因為這個是一個三層復制,MHA manager會報錯並停止,設置這個參數之后,MHA manager不會中斷三層復制架構的監控,只是忽略了第三層,即host3,如果host1掛了,host2將接管host1,被選擇為新主庫,host3繼續從host3復制。
-
ping_interval:這個參數表示mha manager多久ping(執行select ping sql語句)一次master,連續三個丟失ping連接,mha master就判定mater死了,因此,通過4次ping間隔的最大時間的機制來發現故障,默認是3,表示間隔是3秒
-
ping_type:從0.53版本開始支持,默認情況下,mha master基於一個到master的已經存在的連接執行select 1(ping_type=select)語句來檢查master的可用性,但是在有些場景下,最好是每次通過新建/斷開連接的方式來檢測,因為這能夠更嚴格以及更快速地發現TCP連接級別的故障,把ping_type設置為connect就可以實現。從0.56開始新增了ping_type=INSERT類型。
-
secondary_check_script:通常,推薦通過兩個或者更多的網絡路徑來檢測master的可用性,默認情況下,MHA只是通過單個網絡路徑來檢測,即從mha master到master的路線,但是不推薦這么做,mha可以通過secondary_check_script 參數來調用一個外部的腳本來實現兩個或更多個網絡路徑來檢測master的可用性,配置示例如下:
secondary_check_script = masterha_secondary_check -s remote_host1 -s remote_host2
masterha_secondary_check 腳本包含在mha manager的安裝包里,這個腳本適合大多數的場景,但是你可以調用任何你自定義的腳本。
在上述的示例中,mha manager檢測master的存活的網絡路徑是:mha manager-->remote_host1-->master_host和mha manager-->remote_host2-->master_host,如果兩條線路中,mha master到遠程主機的連接是通的,但是遠程主機到master不通,這個腳本返回狀態0,那么mha就判定master死了。 將開始執行故障轉移。如果mha manager到遠程主機都不通,那么這個腳本返回狀態2,mha manager就猜測網絡可能發生了問題了,拒絕執行故障轉移操作。如果兩條線路從頭到位都走通了,那么這個腳本返回狀態3,此時mha master知道主庫是或者的,就不會進行故障轉移操作。
通常來說,remote_host1和remote_host2需要處於本地的兩個不同的網段
mha調用secondary_check_script 腳本自動地傳遞如下參數(不需要你在配置文件中的secondary_check_script 參數中指定這些參數),如果你需要更多的功能,你可以自定義這個腳本:
--user:遠程主機ssh用戶名,如果指定了這個,那么ssh_user參數就會被忽略
--master_host:指定master的主機名(實例)
--master_ip:指定master的IP(實例)
--master_port:指定master的端口號(實例)
PS:運行這個腳本需要依賴perl的 IO::Socket::INET包,這個包包含在perl的5.6.0里,masterha_secondary_check 腳本仍然通過免密鑰的ssh來連接遠程服務器,這個腳本嘗試從遠程服務器建立到master的TCP連接,這個意思是my.cnf中的max_connections 參數對這個么有 影響,如果這個TCP連接成功了,在mysql的Aborted_connects 變量中會增加1 -
master_ip_failover_script:通常在MHA環境下,通常需要分配一個VIP供master用於對外提供讀寫服務,如果master掛了,HA軟件指引備用服務器接管VIP,另外一個通用的方法,是在數據庫中創建一個全局的應用程序名稱與讀寫IP地址之間的全局類目映射( {app1_master1, 192.168.0.1}, {app_master2, 192.168.0.2}, …)來代替VIP地址的使用,在這種情況下,如果你的master掛了,你需要更新這個數據庫中的全局類目映射。第二種方法這里個人覺得跟智能DNS解析類似。
兩種方法各有優缺點,MHA不強制使用哪一種方法,但是允許用戶使用任何IP地址做故障轉移的方案,master_ip_failover_script 參數可以用於實現這個目的,換句話說,你需要自己編寫一個腳本來透明地把應用程序連接到新主庫上。需要在配置文件中定義這個參數,示例如下:
master_ip_failover_script= /usr/local/sample/bin/master_ip_failover
mha manager安裝包中(tar包和githup分支上才有,rpm包沒有)的samples/scripts/master_ip_failover路徑下有一個簡單的腳本
mha manager會調用master_ip_failover_script 這個參數指定的腳本三次,第一次是在進入主庫監控之前(為了檢測腳本的有效性),第二次是將要調用shutdown_script參數的腳本之前,第三次是新主庫應用完成了差異relay log之后,mha manager調用這個腳本會用到如下參數(注意:你不需要在配置文件中這個參數上單獨設置這些)
檢測階段參數:
--command=status
--ssh_user=(current master's ssh username)
--orig_master_host=(current master's hostname)
--orig_master_ip=(current master's ip address)
--orig_master_port=(current master's port number)
關閉當前master的階段參數(注意,到調用shutdown_script的時候,主庫已經被判定為死了):
--command=stop or stopssh
--ssh_user=(dead master's ssh username, if reachable via ssh)
--orig_master_host=(current(dead) master's hostname)
--orig_master_ip=(current(dead) master's ip address)
--orig_master_port=(current(dead) master's port number)
新的master激活階段參數:
--command=start
--ssh_user=(new master's ssh username)
--orig_master_host=(dead master's hostname)
--orig_master_ip=(dead master's ip address)
--orig_master_port=(dead master's port number)
--new_master_host=(new master's hostname)
--new_master_ip=(new master's ip address)
--new_master_port(new master's port number)
--new_master_user=(new master's user)
--new_master_password(new master's password)
如果你在master上使用的是共享VIP,那么在master的shutdown階段就不需要做任何事情,只要在shutdown_script腳本關閉機器的電源之后,在新的master的激活階段,在新的master上分配這個VIP即可,如果你使用的是一個全局類目映射的方案,你可能需要在shutdown死掉的master階段之后,刪除或者更新對應的dead master的記錄。在新的master的激活階段,你可以新增或者更新對應的新的master的記錄,然后,你可以做一些事情(如:在新主庫上執行set global read_only=0;以及創建數據庫用戶的寫權限),以便應用程序就可以在新的主庫上寫入數據了
mha manager會檢測腳本執行退出的代號,如果是0或者10,mha manager則繼續操作,如果返回的是0和10以外的代號,mha manager停止並中斷故障轉移,默認情況下,這個參數為空,所以,默認情況下mha不會調用這個腳本做任何事情。 -
master_ip_online_change_script:這是一個與master_ip_failover_script 參數很接近的參數,但是這個參數不使用故障轉移命令,而是master的在線change命令(masterha_master_switch --master_state=alive),使用如下參數(注意:你不需要在配置文件中這個參數上單獨設置這些):
凍結當前主庫寫操作階段的參數:
--command=stop or stopssh
--orig_master_host=(current master's hostname)
--orig_master_ip=(current master's ip address)
--orig_master_port=(current master's port number)
--orig_master_user=(current master's user)
--orig_master_password=(current master's password)
--orig_master_ssh_user=(from 0.56, current master's ssh user)
--orig_master_is_new_slave=(from 0.56, notifying whether the orig master will be new slave or not)
允許新的主庫寫階段的參數:
--command=start
--orig_master_host=(orig master's hostname)
--orig_master_ip=(orig master's ip address)
--orig_master_port=(orig master's port number)
--new_master_host=(new master's hostname)
--new_master_ip=(new master's ip address)
--new_master_port(new master's port number)
--new_master_user=(new master's user)
--new_master_password=(new master's password)
--new_master_ssh_user=(from 0.56, new master's ssh user)
在凍結當前主庫寫的階段,mha manager在當前主庫上執行FLUSH TABLES WITH READ LOCK,你可以寫任何的邏輯來優雅地實現主庫的切換(參考http://www.slideshare.net/matsunobu/automated-master-failover/44),在新的master允許寫的階段,你可以做和master_ip_failover_script腳本的第三階段幾乎一樣的事情,例如:在新的主庫上創建寫權限用戶和執行set global read_only=0語句,或者更新全局類目映射記錄,如果這個腳本執行返回狀態嗎是0或者10以外的值,mha manager將終止並停止master在線切換操作。默認這個參數為空,mha不會調用這個參數做任何事情,在mha manager的tar包和githup分支下的samples/scripts/master_ip_online_change路徑下有一個簡單的腳本。 -
shutdown_script:你可能想要強制關閉master節點來避免master節點重新啟動服務,這對於避免腦裂來說是很重要的,示例:
shutdown_script= /usr/local/sample/bin/power_manager
在mha manager的tar包和github的分支的samples/scripts/power_manager路徑下有一個簡單的腳本,在調用這個腳本之前,mha manager內部會通過ssh去檢測master是否可達,如果ssh可達(主機OS活着但是mysqld掛了),mha manager使用如下參數:
--command=stopssh
--ssh_user=(ssh username so that you can connect to the master)
--host=(master's hostname)
--ip=(master's ip address)
--port=(master's port number)
--pid_file=(master's pid file)
如果master通過ssh不可達,那么mha manager就會使用如下參數:
--command=stop
--host=(master's hostname)
--ip=(master's ip address)
這個腳本工作流程如下:
如果通過--command=stopssh參數,這個腳本通過ssh過去master上kill -9殺掉mysqld和mysqld_safe進程,如果同時也通過--pid_file參數,這個腳本通過ssh過去主庫上只kill -9殺掉指定的進程號,不會殺掉所有的進程,這個對在master上運行多實例的時候有幫助,如果通過ssh停止成功,這個腳本退出狀態是10,如果退出狀態是10,mha manager隨后就通過ssh連接到master保存必要的binlog,如果這個腳本通過ssh連接master失敗,或者mha manager是使用的參數 --command=stop,這個腳本就會嘗試關閉機器的電源,關閉機器的命令依賴硬件(For HP(iLO), 通常是ipmitool or SSL,For Dell(DRAC), 通常是dracadm),如果關閉電源成功,這個腳本的退出狀態是0,否則退出的狀態是1,如果這個腳本的退出狀態是0,則mha manager開始執行故障轉移過程,如果這個狀態是0和10以外的其他狀態,則mha終止故障轉移,默認這個參數為空,所以mha不會調用這個參數做任何事情。
另外,mha manager開始監控的時候會調用shutdown_script 參數,在這次調用會使用以下參數,在這里可以檢測腳本的設置,控制電源需要高度依賴硬件,所以建議要檢測電源的狀態,如果發現什么問題,你可以在啟動監控程序之前去解決。
--command=status
--host=(master's hostname)
--ip=(master's ip address) -
report_script:在故障轉移完成或者說因為錯誤而終止的時候,你可能希望發送一個報告出來,這就是使用report_script 參數的目的,mha manager通過如下參數使用這個腳本:
--orig_master_host=(dead master's hostname)
--new_master_host=(new master's hostname)
--new_slave_hosts=(new slaves' hostnames, delimited by commas)
--subject=(mail subject)
--body=(body)
默認情況下,這個參數是空的,mha manager不會調用這個參數做任何事情,在mha manager的tar包和github分支的samples/scripts/send_report路徑下有一個簡單的腳本。 -
init_conf_load_script:這個腳本在你不想在配置文件中設置純文本的信息的時候使用(比如:password和repl_password),從這個腳本返回name=value的鍵值對,它可以作為全局配置文件參數,示例腳本內容如下:
#!/usr/bin/perl
print "password=$ROOT_PASS\n";
print "repl_password=$REPL_PASS\n";
這個參數默認為空,所以mha manager不會調用這個參數做任何事情
6、mha注意事項
-
MHA的選舉出latest slave之后,對於non-latest slaves從庫之間補日志是並行的,所以,如果從庫超過10個,可能會出現部分slave恢復失敗的情況,因為ssh默認的配置是10個並發連接,需要修改 /etc/ssh/sshd_config中的MaxStartups變量為大於10的值,官網原文如下:
MHA Manager internally executes recovery in parallel. When generating differential relay log files, MHA connects to the latest slave via SSH in parallel and generates and sends differential relay logs to non-latest slaves. If you have tens of slaves or consolidate tens of MySQL instances within single OS, sshd might reject SSH connection requests, which will cause slave recovery errors. To avoid this issue, raise MaxStartups parameter in /etc/ssh/sshd_config (default 10) and restart sshd. -
MHA不支持串行復制結構,如:master1->master2->slave3,不支持slave3的監控和數據恢復,只支持master1和master2之間的故障切換,所以,MHA中要使用雙主,只能是master1->(master2,slave3)的並行復制結構,官網原文如下:
MHA does not support three or more tier replication structure by default(i.e. Master1 -> Master2 -> Slave3). MHA does failover and recover only slaves that directly replicate from the current primary master. MHA can manage master1 and master2 and promote master2 when master1 crashes, but MHA can not monitor and recover slave3 because slave3 replicates from different master(master2). To make MHA work with such structures, either configure as below. -
使用mysql 5.1+版本的mysqlbinlog命令,因為這個版本之后才支持row格式,如果使用低於這個版本的,將無法解析binlog做數據恢復,官網原文如下:
MHA uses mysqlbinlog for applying binlog events to target slaves. If the master uses row based format, row based events are written in the binary log. Such binary logs can be parsed by mysqlbinlog in MySQL 5.1 or higher only because mysqlbinlog in MySQL 5.0 does not support row based format. mysqlbinlog (and mysql) version can be checked as below. -
作為備用主庫,一定要開啟log-bin,MHA會內部檢測log-bin的設置,沒有開啟binlog的從庫將不能被提升為新主庫,如果沒有任何從庫開啟log-bin,MHA即將不會執行故障轉移,官網原文如下:
If current slaves do not set log-bin, obviously they can not be the new master. MHA Manager internally checks log-bin settings, and do not promote them to new master. If none of the current slaves set log-bin, MHA Manager does not proceed failover. -
所有從庫的復制過濾規則必須相同,MHA啟動的時候會檢測復制過濾規則,如果有所有從庫的過濾規則有不一樣的情況,將拒絕啟動、拒絕做故障轉移操作,官網原文如下:
Replication filtering rules (binlog-do-db, replicate-ignore-db, etc) must be the same on all MySQL servers. MHA checks filtering rules at startup, and doesn't start monitoring or failover if filtering rules are not same each other. -
作為復制的帳號,必須在主庫和備用主庫都存在,因為在做故障轉移的時候,MHA會使用這個復制帳號讓其他從庫change master過來(這個復制帳號指的就是寫在配置文件中的那個repl_user),個人建議所有節點帳號相同,官網原文如下:
After master failover completes, all other slaves execute CHANGE MASTER TO statement. To start replication, a replication user (with REPLICATEION SLAVE privilege) must exist on the new master. -
mysql默認情況下,會把sql線程重放完的relay log清理掉,但是 因為從庫恢復需要用到relay log,所以需要關閉從庫自動清理relay log的操作,但是有個問題需要注意,如果relay log堆積太多,而你一次性手動清理的relay log太多,可能會因為磁盤資源占用過多而導致復制延遲,所以,要么周期性的手動清理relay log,要么使用硬鏈接清理(使用自帶的命令purge_relay_logs做清理,這個命令是使用創建硬鏈接的方式清理relay log),官網原文如下:
By default, relay logs on slave servers are automatically removed if SQL threads have finished executing them. But such relay logs might still be needed for recovering other slaves. So you need to disable automatic relay log purge, and periodically purges old relay logs. But you need to care about replication delay issues when manually purging relay logs. On ext3 filesystem, removing large files takes significant time, which will cause serious replication delay. To avoid replication delay, tentatively creating hard links of the relay logs helps. See the two slides for details.
PS:可以把這個命令放到計划任務里,做定時調用(建議在不同的從庫上,調用時間錯開),如:
cat /etc/cron.d/purge_relay_logs
# purge relay logs at 5am
0 5 * * * app /usr/bin/purge_relay_logs --user=root --password=PASSWORD --disable_relay_log_purge >> /var/log/masterha/purge_relay_logs.log 2>&1
-
不要使用load data infile語句,當使用基於SBR的binlog格式在主庫崩潰恢復完成之后,MHA可能無法獲得relay log差異日志,另外,如果你使用了一些非事務引擎或者太老的mysql版本,會有一些已知的問題,另外,也可能導致復制延遲,官網原文如下:
When the master is crashed just after completing LOAD DATA INFILE with Statement Based Binary Logging, MHA might not be able to generate differential relay log events, if you use non-transactional storage engine or too old MySQL version (i.e. 5.0.45, etc). Using LOAD DATA INFILE with SBR has some known issues and it's deprecated from MySQL 5.1. LOAD DATA INFILE also causes significant replication delay, so there are not positive reasons to use it.
If you want to use LOAD DATA, SET sql_log_bin=0; LOAD DATA … ; SET sql_log_bin=1; is more recommended approach. -
如果使用GTID復制,那么所有節點的mysql版本必須大於等於5.6,且必須所有節點都開啟GTID,至少有一個節點使用Auto_Position =1,官網原文如下:
Starting from MHA 0.56, MHA supported both GTID based failover and traditional relay log based failover. MHA automatically distinguishes which failover to choose. To do GTID based failover, all of the following is needed.
Using MySQL 5.6 (or later)
All MySQL instances use gtid_mode=1
At least one of the instances has Auto_Position enabled