在slave上有兩個線程:io線程和sql線程
io線程接收master的二進制日志信息並寫入到本地的relay log中;sql線程執行本地relay log中的信息。
io線程讀取到的二進制日志當前位置信息寫在master.info中;sql線程讀取到的當前relay log位置信息寫在realy-log.info文件中
存在的問題就是相應的內容寫入文件后,並不能都實時刷新到磁盤上。當mysql實例crash后,對應的位置信息就可能不一致。
在5.6中可以set sync_master_info = 1和 sync_relay_log_info =1來確保每個事務結束后對應的信息被寫入磁盤。
但是復制信息是在事務提交后才寫的,如果在事務提交后slave發生了crash,而realy-log.info信息還沒有被更新,實例重啟后就可能會導致事務執行兩次,就可能會發生復制錯誤。當然也可能對復制沒有影響。
5.6中,引進了兩個參數relay_log_info_repository、master_info_repository
設置relay_log_info_repository=table,就會創建表mysql.slave_relay_log_info,並將realy-log.info文件中的信息寫入到該表中。
設置master_info_repository=table,就會創建表mysql.slave_master_info,並將master.info文件中的信息寫入該表。
這個方法很簡單,就是把SQL線程的事務和更新mysql.slave_relay_log_info的語句看成一個事務處理,這樣就會一直同步的.
雖然解決了sql線程的問題,但是io線程的問題還沒有解決,因為更新slave_master_info表跟事務沒有關系。那么如何讓msyql server更新該表呢?
於是又引入了參數sync_master_info,5.6.6之后默認值是10000。
當master_info_repository=file,sync_master_info=n的值大於0,表示n個events之后刷新到磁盤;如果n值為0,表示如何刷新到磁盤取決於操作系統。
當master_info_repository=table,sync_master_info=n的值大於0,表示n個events之后更新表mysql.slave_master_info;如果n值為0,表示不更新mysql.slave_master_info。
還有更優雅的方法,使用參數relay_log_recovery = ON,但是設置這個參數生效,需要服務器重啟。
開啟該參數,重啟server后,io線程拋棄現有的IOthread的偏移量,從slave_relay_log_info表中獲取當前的IO線程偏移量,這樣你就不需要以為crash-safe存儲IO線程的信息到表里。也就是說master_info_repository = TABLE不是必須的。
最后注意,relay_log_info_repository = TABLE和 sync_relay_log_info是 沒有關聯的。所以你可以放心的從配置文件中移除sync_relay_log_info。