標籤:mysql mha 解決方案 工作原理 mysql events 記錄
一、MHA工作原理:
1、主庫掛了,但是主庫的binlog都被全部從庫接收
此時會選中應用binlog最全的一台從庫作為新的主庫,其他從主只需要重新指定一下主庫即可(因為此時,所有從庫都是一致的,所以只需要重新指定一下從庫即可)。
2、主庫掛了,所有的binlog都已經被從庫接收了,但是,主庫上有幾條記錄還沒有sync到binlog中,所以從庫也沒有接收到這個event,如果此時做切換,會丟失這個event。
此時,如果主庫還可以通過ssh訪問到,binlog檔案可以查看,那麼先copy該event到所有的從庫上,最後再切換主庫。
3、如果使用半同步複製,可以極大的減少此類風險。
主庫掛了,從庫上有部分從庫沒有接收到所有的events
選擇出最新的slave,從中拷貝其他從所缺少的events
問題1、
如何確定哪些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
由Google開發的外掛程式。
二、MHA的實施步驟
1、從down的主上面擷取到binlog事件
2、確定最新(最全)的從庫
3、分別應用不同的relay log事件到其他從庫
4、應用從主庫上擷取的binlog事件(發生故障時的事件)
5、提升一個從庫為新的主庫(此時從庫已經一致)
6、將其他從庫的主庫重新指定
同時,自動檢測主庫故障。
三、如何確定最近從庫以及丟失的events
1、Master_Log_File,Read_Master_Log_Pos 可以確定(從庫的IO線程)讀取主庫的binlog的最新進度。
2、Relay_Log_File,Relay_Log_Pos 確定SQL線程執行本地Relay_Log的最新進度。
3、由於Relay_Log的進度和binlog是不一樣的。所以如果只看Relay_Log的資訊無法確定執行事件的實際位置
Relay_Master_Log_File,Exec_Master_Log_Pos 本地SQL線程實際上執行binlog位置(用於計算seconds_behind_master)
4、各個從庫之間,比較Master_Log_File,Read_Master_Log_Pos可以確定哪台從庫接收到的日誌是最完整的。
5、當找出最新最全的從庫之後,應用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需要考慮的注意事項:
1、如果使用mysqlbinlog開啟binlog和relaylog,會自動在文本裡面添加rollback關鍵字所以要在日誌中清理掉由mysqlbinlog添加的rollback。
ROLLBACK /* added by mysqlbinlog */
2、由於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使用者恢複的情形出現。
3、要確定SQL線程是否執行完所有的events
1)、等待事物執行
2)、select MASTER_POS_WAIT(master_log_file,read_master_log_pos);
如果所有從庫已經與主庫一致了,上面的命令失效
如果只有部分事物記錄傳送到從庫,SQL線程也不會同步到Read_Master_Log_Pos。
3)、show processlist查看輸出。提示:"Has read all relay log;waiting for the slave I/O thread to update it"
4、要處理惡意查詢
惡意查詢:insert into t1 values(0,0,"ROLLBACK");
5、有多個從庫時,並行恢複。
6、採用ROW FORMAT
對於採用row格式記錄的日誌、
可能出現多個"#at"條目+相同的"end_log_pos"條目。
Table_map+Write_rows+STMT_END
四、故障自動轉移的內容:
1、檢測master failure
2、Node Fencing(通過幹掉故障master 避免腦裂)
3、更新寫入IP(VIP)
條件:
通過指令碼完成自動轉移,同時再故障發生時要自動呼叫指令碼.
1、確保檔案和對應的目錄存在,SSH互信成功----避免因為低級錯誤導致轉移失敗
2、如果有從程式庫伺服器掛掉,或者SQL線程掛掉,或者在8個小時內發生過轉移了----都不再執行容錯移轉
如果發生故障:
發送郵件警示
停掉新主庫上的備份任務
更新內部工具的管理地址(從舊庫指向新庫)..
五、MHA工具介紹
1、在manager上
master_monitor:檢測master狀態
master_switch:執行容錯移轉(手動執行,如果自動則要使用masterha_manager)
masterha_manager:啟動mha,執行mha的管理操作
2、在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以前的版本
本文出自 “IT--小哥” 部落格,謝絕轉載!
mysql高可用之MHA原理