一、概述
官方文檔中對relay_log_recovery參數的解釋
Enables automatic relay log recovery immediately following server startup. The recovery process creates a new relay log file, initializes the SQL thread position to this new relay log, and initializes the I/O thread to the SQL thread position. Reading of the relay log from the master then continues.
上面的英文看不懂,沒關系,后面有大白話的翻譯加實驗,不怕你不懂。
現在我們考慮一個問題,假設當從庫意外宕機后,同時從庫的relay log也一起損壞了,而主庫的日志已經傳到了從庫,只是從庫還沒有來得及應用這些日志,那么從庫該如何處理?
二、結論
1. 在從庫中將relay_log_recovery不設置或者設置為off,如果碰到上面的情形,從庫會丟失那些沒有應用的日志,主從會不一致。
2. 在從庫中將relay_log_recovery設置為on,假如果碰到上面的情形,從庫會自動放棄所有未執行的relay log,重新生成一個relay log,並將從庫的io線程的position重新指向新的relay log。並將sql線程的position退回到跟io線程的position保持一致,重新開始同步,這樣在從庫中事務不會丟失。這個參數建議開啟。是不是很繞,沒關系,看實驗。
三、實驗
1. 實驗環境介紹
mysql版本:5.7.25,操作系統版本:centos6.10
主庫ip:10.40.16.61,從庫ip:10.40.16.62
從庫的參數文件中加入了參數skip-slave-start,防止從庫自動啟動slave。
2. 將relay_log_recovery設置為off
默認情況這個參數就是off,所以無須設置
從上面的輸出可以看到,當前主從是同步的,而且從庫的relay_log_recovery參數是OFF
關閉從庫的sql線程
(root@localhost)[hello]> stop slave sql_thread;
主庫隨意做幾個更改
(root@localhost)[hello]> insert into t1 values(20);
(root@localhost)[hello]> insert into t1 values(30);
查看從庫的relay log
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000010
可以看到主庫已經將日志傳送到relay log中了,只是從庫沒有執行而已。現在模擬從庫意外宕機。
[root@mysqlb relaybin]# reboot
等從庫節點啟動完畢后刪除從庫最后的relay log
[root@mysqlb relaybin]# rm -f slave-relay-bin.000010
然后啟動從庫
[root@mysqlb relaybin]# service mysql start
查看relay log目錄,發現又生成了一個slave-relay-bin.000010
去看看這個重新生成的slave-relay-bin.000010內容
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000010
可以看到啥都沒有,這是因為數據庫在重啟的時候,會自動重新生成一個relay log,但是這個特性跟上面提到的參數relay_log_recovery沒有任何關系
再去從庫看看當前的從庫狀態
發現與重啟前的狀態信息是的一致的
啟動從庫的slave線程,再去從庫看看當前的從庫狀態
可以看到從庫又開始同步了,而且Exec_Master_Log_Pos=Read_Master_Log_Pos,還重新生成了一個slave-relay-bin.000011
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000010
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000011
可以看到都是些空事務,也就是從庫對於那些還沒有執行的語句,全部拋棄了。強制將Exec_Master_Log_Pos移到了Read_Master_Log_Pos。
看到了吧,t1表中的20和30這兩條記錄就丟失了。
2. 將relay_log_recovery設置為on
在從庫參數文件中設置參數(relay_log_recovery = 1)並重啟從庫
停掉重庫的sql線程
(root@localhost)[hello]> stop slave sql_thread;
從庫查看slave log
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000013
可以看到日志已經進入到slave log中了
現在模擬從庫意外宕機,等啟動后刪除從庫最新的relay log,跟第一個實驗步驟一致
[root@mysqlb relaybin]# reboot
[root@mysqlb relaybin]# rm -f slave-relay-bin.000013
[root@mysqlb relaybin]# service mysql start
查看從庫的狀態
可以看到Read_Master_Log_Pos已經由重啟前的5429退回到了5124,跟Exec_Master_Log_Pos保持一致。
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000013
從庫照例又生成了一個slave-relay-bin.000013,不過這個依然是個空日志
啟動從庫的slave線程
(root@localhost)[hello]> start slave;
查看從庫的狀態
可以看到Exec_Master_Log_Pos沒變,Read_Master_Log_Pos增長了,我就在這里不明白,為什么sql線程不去執行日志呢,而且還多了一個線程System lock?
查看relay log
[root@mysqlb relaybin]# mysqlbinlog -vv slave-relay-bin.000014
可以看到啟動slave線程后,又生成了一個新的relay log,而且之前沒有執行的relay log條目的確又進到這個新的relay log中了。但是此刻sql線程並沒有執行relay log,應該就是system lock在作怪。
可以看到現在Slave_SQL_Running_State已經不是System lock了。
在從庫查看t2表的數據
可以看到數據並沒有任何丟失,由此證明在從庫中將relay_log_recovery設置為ON,能避免由於從庫relay log損壞導致的主從不一致的情形。
四、總結
在從庫中最好將relay_log_recovery設置為ON。如果有哪位高手知道system lock是個什么情況,期待您的留言。寫作不易,如果幫到了你,希望你點個贊,鼓勵下博主。