最近一位同窗遇到的案例:凌晨數據庫意外宕機,要求在一主兩從的基礎上,搭建MHA作故障切換。在部署測試中遇到一些問題找到我,交流的過程挖出一些以前忽略的坑,感謝這位同窗無私分享!
• GTID環境,KILL主庫,新主庫和從庫丟失數據(以前已知)
• 在數據庫進程掛掉、數據庫服務器關機或重啓、開啓防火牆、關閉網絡服務等情況下,測試MHA是否正常切換(以前沒考慮腦裂問題)
• 線上部分環境GTID,Auto_Position=0,故障切換會變成GTID,Auto_Position=1(以前沒考慮)
• 梳理故障切換流程(以前梳理)html
需在配置文件將Master/Binlog Server配置到[binlogN],才能補全Dead Master上的差別數據,不然只應用到Latest Slave
發散:[binlogN]指定到Binlog Server,kill -9 master_mysqld,MHA是從Binlog Server上獲取仍是從Dead Master上獲取差別binlog?
指定到Binlog Server就從Binlog Server上獲取,指定到Dead Master就到Dead Master獲取;若是沒有指定,就不會補全差別數據mysql
在數據庫進程掛掉,數據庫服務器關機或重啓、開啓防火牆、關閉網絡服務等情況下,測試MHA是否正常切換
MySQL5.7.21,基於Row+Gtid搭建的一主兩從複製結構:Master132->{Slave13三、Slave134};VIP在132上,mha-manager 0.56在134上git
測試場景 | XX.132 | XX.133 | XX.134 | 說明 |
132:kill -9 mysqld | 不可用 | 主 | 從 | MHA正常切換,數據不丟失 |
132:關閉或重啓132服務器 | 不可用 | 主 | 從 | MHA正常切換,數據可能丟失 |
134:iptables -I INPUT -s XX.132 -j DROP | 可用 | 主 | 從 | MHA正常切換,原主庫正常訪問,133成爲新主庫,132和133同時存在VIP |
132:service network stop/ifconfig eth0 down | 不可用 | 主 | 從 | MHA正常切換,數據可能丟失 |
注:上述表格是配置[binlogN]指定到Binlog Server,沒有指定secondary_check_script的測試結果
關閉數據庫服務器,數據可能丟失的緣由:Binlog Server是異步,高併發下binlog延遲能夠理解
開啓防火牆,模擬主庫與mha-manager不通信,出現腦裂。配置文件添加"secondary_check_script=masterha_secondary_check -s remote_host1 -s remote_host2",remote_host一、remote_host2儘可能與mha-manager、MySQL Server處於不一樣網段github
線上部分環境GTID,Auto_Position=0,故障切換會變成GTID,Auto_Position=1
• 有何風險
若是S1從庫的GTIDs存在空洞,S2從庫的GTIDs正常,隨着時間推移,S2將S1上GTIDs空洞對應的binlog刪除。此時發生故障切換,且選擇S2作爲新Master,在S1 change master to S2 master_auto_position=1會報錯sql
Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'
從庫存在GTIDs空洞可能會致使切換異常:VIP正常切換,新主可用,新從到新主之間的複製報錯,只有修復主從報錯,纔會作後續操做(new master cleanup、Failover Report、send mail)
• 爲什麼不直接修改成GTID,Auto_Position=1
Slave GTIDs<Master GTIDs,若是Diff GTIDs對應的binlog在Master已被purge,修改成Auto_Position=1會繼續報錯
Slave GTIDs>Master GTIDs,5.7下主從直接報錯
• 如何解決
修改源碼~~~shell
shell> vim /usr/share/perl5/vendor_perl/MHA/ServerManager.pm 1550 return 1 if ( $_->{use_gtid_auto_pos} ); -->修改成 1550 #return 1 if ( $_->{use_gtid_auto_pos} ); shell> vim /usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm 367 if ( !$_server_manager->is_gtid_auto_pos_enabled() ) { 368 $log->info("GTID (with auto-pos) is not supported"); -->修改成 367 if ( $_server_manager->is_gtid_auto_pos_enabled() !=1 ) { 368 $log->info("GTID (with auto-pos) is not supported");
爲啥這樣修改表示看不懂,感謝順子(另外一位同窗)分享~
注意:傳統複製(gtid_mode=off),MHA不會利用Binlog Server補全差別數據(又是一個坑●-●)數據庫
Binlog Server
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.
一、從庫暫停Slave Thread->主庫寫數據->主庫flush log、purge log->從庫啓動Slave Thread->報錯,缺失binary log
手工執行change master_auto_position=0;change binlog file & pos;
二、搭建複製時change master_auto_position=0;->複製過程暫停Slave Thread->change new_file & new_pos->從庫啓動Slave Thread
master_auto_position=1,Slave鏈接Master時,會把Executed_Gtid_Set中的GTIDs發給Master,Master會跳過Executed_Gtid_Set,把沒有執行過的GTIDs發送給Slave
狀況1:再次change master_auto_position=1;它依舊會去查找那些被purge的binlog,而後拋出錯誤
狀況2:再次change master_auto_position=1;只要主上對應binlog沒被purge,它能自動將空洞GTID補全
前提:Master沒有對GTIDs空洞相應的記錄進行DML操做,否則複製早就報錯了,可能就錯過這個坑~不過仔細想一想,從庫原本就有空洞,複製也沒報錯,側面反映Master沒有對GTIDs空洞相應的記錄進行DML操做
擴展閱讀:[MySQL FAQ]系列 — 5.6版本GTID複製異常處理一例vim
Slave GTIDs>Master GTIDs,relay-log是如何獲取及應用服務器
• GTID,auto_position=0 Master Executed_Gtid_Set:90b30799-9215-11e7-8645-000c29c1025c:1-14 Slave set global Gtid_Purged='90b30799-9215-11e7-8645-000c29c1025c:1-6:8-24'; -->Master寫入一條數據 Master Executed_Gtid_Set:90b30799-9215-11e7-8645-000c29c1025c:1-15 Slave Retrieved_Gtid_Set: 90b30799-9215-11e7-8645-000c29c1025c:15 Executed_Gtid_Set: 90b30799-9215-11e7-8645-000c29c1025c:1-6:8-24
新寫入的binlog會寫到從庫的relay-log,可是不會應用(能夠經過查看數據、解析日誌確認)!網絡
• GTID,auto_position=1 change master to master_auto_position=1; 啓動複製報錯 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: Slave has more GTIDs than the master has, using the master`s SERVER_UUID. This may indicate that the end of the binary log was truncated or that the last binary log file was lost, e.g., after a power or disk failure when sync_binlog != 1. The master may or may not have rolled back transactions that were already replica
relay-log獲取
Auto_Position=0,若是開啓relay-log自動修復機制,發生crash時根據relay_log_info中記錄的已執行的binlog位置從master上從新獲取寫入relay-log
Auto_Position=1,Slave鏈接Master時,會把Executed_Gtid_Set中的GTIDs發給Master,Master會跳過Executed_Gtid_Set,把沒有執行過的GTIDs發送給Slave。若是Slave上的GTIDs大於Master上的GTIDs,5.7下直接報錯,5.6下不會報錯(有環境的自行驗證,順便看看relay-log會不會有記錄寫入)
relay-log應用
若是relay-log中的GTIDs包含在Executed_Gtid_Set裏,則不會apply-log
MHA在傳統複製和GTID複製下,主庫發生故障,如何選舉New Master,如何修復差別數據
詳細流程請參考:MHA-手動Failover流程(傳統複製>ID複製)