資料庫作為儲存資料的元件,資料的一致性一定是要保證的前提,今天給出兩個場景來分析資料不一致的原因。
binlog同步模式導致主從不一致
在MYSQL 中主庫向從庫同步資料是利用binlog記錄修改操作,然後將binlog傳遞給從庫進行復制,binlog的格式有3種,
row
在對update,delete,insert語句進行記錄時會進行修改的行資料進行記錄。row
格式的壞處在於比較佔用空間,比如更新十萬行資料,那麼row
格式將會把10萬資料記錄下來。
statement
只會將原始的sql語句記錄下來。但是這種格式可能會引起主備不一致。
mixed
是前面兩種格式的混合,MYSQL會自己去判斷這條sql是不是會造成主備不一致,將引起主備不一致的sql記錄成row
格式。
statement 為什麼會主備不一致?
舉一個例子來說明下,statement主備不一致的原因,例如下面的sql
update navigation.t_account set id = uuid();
當你使用 類似uuid或者now這種動態函式時,那麼在主庫的生成結果將會和從庫不同。造成資料的主備不一致。
為什麼大多數時候我們還是用row
大多時候,我們還是用row
格式寫入binlog,這樣帶來的好處是便於恢復資料
,下面我舉例說明下,
當你執行錯delete語句
,能夠透過binlog日誌找到刪除行的所有欄位資訊,不過需要注意的是,需要將binlog_row_image
引數設定為FULL
,才會記錄所有欄位資訊,如果設定為MINIMAL
則只會記錄刪除欄位資訊。當你執行錯update語句
,透過binlog記錄的修改前後的整行資料,對資料進行恢復。當你執行錯insert語句
,能夠透過binlog找到插入資料的id,對錯誤插入的資料進行刪除。
所以,為了避免主從不一致,還是選用row
格式記錄binblog吧,或者至少還是選用mixed
主備切換導致主從不一致
第二種主從不一致的場景是發生在主備切換時,我先直接說下結論,主備切換方式其實分可靠性優先方式與可用性優先方式。
可靠性優先方式,MYSQL服務可能會存在短暫的不可提供服務的時間段,可用性優先則是保證MYSQL在切換過程中都是可用的。
為了方便,下面我將主主資料庫稱為master,從資料庫稱為slave。
可靠性優先方式
1,判斷slave是否已經 seconds_behind_master
,是否小於5s或更短,seconds_behind_master
代表主從同步延遲的時間,如果小於5s,則繼續下一步。
2,修改master的readonly
引數為true, 將master變為只讀狀態。
3,判斷slave的主從同步延遲是否變為0,即seconds_behind_master 等於0,等於0後,繼續下一步。
4,修改 slave的 readonly
引數改為false,將slave變為可讀可寫狀態。
5,將業務請求轉發到slave,原先master,修改為新master的從庫。
這個切換過程,資料庫是有一段時間不可寫的,必須等待slave主從延遲同步變為0以後才行,所以這也是為什麼要在seconds_behind_master
在一個較小的值才開始進行主備切換的原因。
可用性優先方式
接著看下保證可用性優先的主備切換方式,在上述主備切換步驟中,我們去掉第三個步驟,也就是不等到主從同步完成就去切換主備。
現在假設現在的binlog為 row
格式。表定義為
mysql> CREATE TABLE `t` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `c` int(11) unsigned DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
insert into t(c) values(1),(2),(3);
業務此時進行插入操作,
insert into t(c) values(4);
insert into t(c) values(5);
當在執行完第一個sql時,進行主備切換,且假設此時備庫並沒有完成第一條sql的同步。如下圖所示,在插入4這條資料時,將slave改為可寫,接著業務系統後續的寫就往slave寫入了5這條資料。注意此時master的4這條資料還沒有同步到slave。
接著開始準備更改主備關係,如下圖所示,更改關係前,有可能slave才會進行來自master的4這條資料的寫入,但是因為slave中已經有id為4的資料了,所以會導致插入失敗。
修改slave為master後,插入到之前從庫的(4,5)這條資料 會同步到新的slave主機(即舊master),但是這個時候也會因為舊master有id為4的這條資料導致同步失敗。主備同步就會自動停止。
可以看到,最後主從資料庫中有id等於4這條資料不一樣。
所以,可用性優先的主備切換方式是有可能導致主備不一致的。
資料庫最重要還是資料的正確性
,拿許多業務場景來說,如果資料錯亂了,是較難恢復的,但是如果業務失敗了,還可以透過重試重新填充資料,怕就怕成功一半,失敗一半。所以主備切換的時候儘量還是可靠性優先方式比較好。
最後,
自薦一波✅:
歡迎朋友們關注我的公眾號📢📢:【藍胖子的程式設計夢】!
學習容器知識🐳,效能監控🚀,Golang🐋 相關程式設計知識