MHA工做原理:node
主庫掛了,可是主庫的binlog都被所有從庫接收mysql
此時會選中應用binlog最全的一臺從庫做爲新的主庫,其餘從主只須要從新指定一下主庫便可(由於此時,全部從庫都是一致的,因此只須要從新指定一下從庫便可)。sql
主庫掛了,全部的binlog都已經被從庫接收了,可是,主庫上有幾條記錄尚未sync到binlog中,因此從庫也沒有接收到這個event,若是此時作切換,會丟失這個event。數據庫
此時,若是主庫還能夠經過ssh訪問到,binlog文件能夠查看,那麼先copy該event到全部的從庫上,最後再切換主庫。服務器
若是使用半同步複製,能夠極大的減小此類風險。app
主庫掛了,從庫上有部分從庫沒有接收到全部的eventsssh
選擇出最新的slave,從中拷貝其餘從所缺乏的events異步
問題一、工具
如何肯定哪些event沒有成功接收性能
問題二、
如何讓全部從庫保持一致
致使複製問題的緣由是由於MySQL採用異步複製,並不保證全部事件被從庫接收
對於此類問題的解決方案:
Heartbeat + DRBD
代價:額外的被動master,而且不處理任何流量。
性能:爲了保證事件被及時寫入,innodb_flush_log_at_trx_commit=1,sync_binlog=1. 這樣就會致使性能急速降低
MySQL Cluster
真正的高可用,可是隻支持InnoDB
Semi_synchronous Replication (5.5+)
半同步複製極大減小了"binlog事件只存在於master上"的風險。
保證至少有一臺從庫接收到了提交的binlog事件。其餘的從可能沒有接收,可是不影響提交了
Global Transaction ID
由谷歌開發的插件。
MHA的實施步驟
一、從down的主上面獲取到binlog事件
二、肯定最新(最全)的從庫
三、分別應用不一樣的relay log事件到其餘從庫
四、應用從主庫上獲取的binlog事件(發生故障時的事件)
五、提高一個從庫爲新的主庫(此時從庫已經一致)
六、將其餘從庫的主庫從新指定
同時,自動檢測主庫故障。
---------------------------------------------------------------------------------
如何肯定最近從庫以及丟失的events
一、Master_Log_File,Read_Master_Log_Pos 能夠肯定(從庫的IO線程)讀取主庫的binlog的最新進度。
二、Relay_Log_File,Relay_Log_Pos 肯定SQL線程執行本地Relay_Log的最新進度。
三、因爲Relay_Log的進度和binlog是不同的。因此若是隻看Relay_Log的信息沒法肯定執行事件的實際位置
Relay_Master_Log_File,Exec_Master_Log_Pos 本地SQL線程實際上執行binlog位置(用於計算seconds_behind_master)
四、各個從庫之間,比較Master_Log_File,Read_Master_Log_Pos能夠肯定哪臺從庫接收到的日誌是最完整的。
五、當找出最新最全的從庫以後,應用diff到其餘從庫
僅僅比較上面2個參數是不夠肯定具體缺失的events
在relay log中日誌開頭會指定是讀哪一個binlog,文尾的end_log_pos表示最後讀到binlog的位置。
經過對比不一樣從庫上,最新的relay_log中的binlog file和end_log_pos位置來對比還有哪些events缺失(每一個at xxx就是一個event)。
----------------------------------------------------------------------------------
若是是一個很大的事務,產生了不少日誌信息(事務只會保存在一個binlog文件中,可是會出如今2個relay_log中。)
面對這種情形,若是隻接受到了部分的events信息。從庫是不會重作這些relay_log。
此時的Master_Log_File,Read_Master_Log_Pos 會指向讀取到的binlog的最新位置(這是IO線程負責的),
而Relay_Master_Log_File,Exec_Master_Log_Pos只會指向最後執行的commit事務。
這樣就保證了不會使數據庫進入不一致狀態。那麼在接受到其餘從庫最新日誌的時候,也是完整的執行一次該事務(即便本身的Relay log已經有部分記錄了)
-----------------------------------------------------------------------------------
MHA須要考慮的注意事項:
一、若是使用mysqlbinlog打開binlog和relaylog,會自動在文本里面添加rollback關鍵字因此要在日誌中清理掉由mysqlbinlog添加的rollback。
ROLLBACK /* added by mysqlbinlog */
二、因爲mha默認關閉relay_log_purge。因此要手動按期清理。
爲了保證在發生故障時,能有足夠多的relay log用戶恢復,因此不該該自動清理。
關閉這個參數以後,SQL線程不會按期清理Relay_log,因此很快會填滿磁盤空間。
Relay_log沒有像binlog同樣有自動過時參數expire_logs_days
按期清理的方式:
set global relay_log_purge=1;
flush logs;/* SQL線程會自動清理多餘的Relay_Log_File */
set global relay_log_purge=0;
若是有較大的日誌,讓SQL線程自動刪,會致使SQL線程鎖住,從庫落後主庫。
ln relay-log.* /tmp/archive_dir/
mysql -e"set global relay_log_purge=1;flush logs;set global relay_log_purge=0;"
rm -rf /tmp/archive_dir/* */
這樣就不會佔用寶貴的SQL線程了。
即使如此也不要在全部的從庫上同一時間執行一個計劃任務(清除Relay_Log),不然會致使沒有Relay_Log用戶恢復的情形出現。
三、要肯定SQL線程是否執行完全部的events
一、等待事物執行
二、select MASTER_POS_WAIT(master_log_file,read_master_log_pos);
若是全部從庫已經與主庫一致了,上面的命令失效
若是隻有部分事物日誌傳送到從庫,SQL線程也不會同步到Read_Master_Log_Pos。
三、show processlist查看輸出。提示:"Has read all relay log;waiting for the slave I/O thread to update it"
四、要處理惡意查詢
惡意查詢:insert into t1 values(0,0,"ROLLBACK");
五、有多個從庫時,並行恢復。
六、採用ROW FORMAT
對於採用row格式記錄的日誌、
可能出現多個"#at"條目+相同的"end_log_pos"條目。
Table_map+Write_rows+STMT_END
-----------------------------------------------------------------------------------------------
故障自動轉移的內容:
一、檢測master failure
二、Node Fencing(經過幹掉故障master 避免腦裂)
三、更新寫入IP(VIP)
經過腳本完成自動轉移,同時再故障發生時要自動調用腳本.
一、確保文件和對應的目錄存在,SSH互信成功----避免由於低級錯誤致使轉移失敗
二、若是有從庫服務器掛掉,或者SQL線程掛掉,或者在8個小時內發生過轉移了----都再也不執行故障轉移
若是發生故障:
發送郵件報警
停掉新主庫上的備份任務
更新內部工具的管理地址(從舊庫指向新庫)..
..
..
..
-------------------------------------------------------------------------------------------
MHA工具介紹
在manager上
master_monitor:檢測master狀態
master_switch:執行故障轉移(手動執行,若是自動則要使用masterha_manager)
masterha_manager:啓動mha,執行mha的管理操做
在node上
save_binary_logs:複製主庫二進制日誌
apply_diff_relay_logs:從最全的slave上生成diff Relay log,應用全部從主庫copy來的的binlog中的events
filter_mysqlbinlog:清理掉有mysqlbinlog工具帶來的ROLLBACK events
purge_relay_logs:在不中止SQL線程的前提下刪除Relay_log
MHA處理案例:
master上內核崩潰
10內檢查master狀態。
肯定master不可用以後power off
選擇新的master,recovery
並行恢復其餘從庫
MHA的限制:
不支持多級複製 M->M->S
不支持日誌爲statment級別(SBR)的load data infile
不支持MySQL5.0之前的版本