http://ourmysql.com/archives/1453
有時候,我們希望將 MySQL 的 relay log 多保留一段時間,比如用於高可用切換後的數據補齊,於是就會設置 relay_log_purge=0,禁止 SQL 線程在執行完一個 relay log 後自動將其刪除。但是在官方文檔關於這個設置有這麼一句話:
Disabling purging of relay logs when using the --relay-log-recovery option risks data consistency and is therefore not crash-safe.
究竟是什麼樣的風險呢?查找了一番後,基本上明白了原因。
首先,爲了讓從庫是 crash safe 的,必須設置 relay_log_recovery=1,這個選項的作用是,在 MySQL 崩潰或人工重啓後,由於 IO 線程無法保證記錄的從主庫讀取的 binlog 位置的正確性,因此,就不管 master_info 中記錄的位置,而是根據 relay_log_info 中記錄的已執行的 binlog 位置從主庫下載,並讓 SQL 線程也從這個位置開始執行。MySQL 啓動時,相當於執行了 flush logs ,會新開一個 relay log 文件,新的 relay log 會記錄在新的文件中。如果默認情況 relay_log_purge=1 時,SQL 線程就會自動將之前的 relay log 全部刪除。而當 relay_log_purge=0 時,舊的 relay log 則會被保留。雖然這並不會影響從庫複製本身,但還是會有地雷:
-
由於崩潰或停止 MySQL 時,SQL 線程可能沒有執行完全部的 relay log,最後一個 relay log 中的一部分數據會被重新下載到新的文件中。也就是說,這部分數據重複了兩次。
-
如果 SQL 跟得很緊,則可能在 IO 線程寫入 relay log ,但還沒有將同步到磁盤時,就已經讀取執行了。這時,就會造成新的文件和舊的文件中少了一段數據。
如果我們讀取 relay log 來獲取數據,必須注意這一點,否則就會造成數據不一致。而保留 relay log 的目的也在於此。因此,在處理 relay log 時必須格外小心,通過其中 binlog 頭信息來確保正確性。
關於如何配置 crash safe 的複製本身的配置,可以參照:
http://blog.itpub.net/22664653/viewspace-1752588/
http://www.innomysql.net/article/34.html
參考資料:
http://blog.booking.com/better_crash_safe_replication_for_mysql.html
https://bugs.mysql.com/bug.php?id=73038
http://bugs.mysql.com/bug.php?id=74324