<bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>

    Loading

    MYSQL 主從不一致的原因分析

    數據庫作為存儲數據的組件,數據的一致性一定是要保證的前提,今天給出兩個場景來分析數據不一致的原因。

    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。

    image.png

    接著開始準備更改主備關系,如下圖所示,更改關系前,有可能slave才會進行來自master的4這條數據的寫入,但是因為slave中已經有id為4的數據了,所以會導致插入失敗。

    image.png
    修改slave為master后,插入到之前從庫的(4,5)這條數據 會同步到新的slave主機(即舊master),但是這個時候也會因為舊master有id為4的這條數據導致同步失敗。主備同步就會自動停止。

    可以看到,最后主從數據庫中有id等于4這條數據不一樣。

    所以,可用性優先的主備切換方式是有可能導致主備不一致的。

    數據庫最重要還是數據的正確性,拿許多業務場景來說,如果數據錯亂了,是較難恢復的,但是如果業務失敗了,還可以通過重試重新填充數據,怕就怕成功一半,失敗一半。所以主備切換的時候盡量還是可靠性優先方式比較好。

    最后,

    自薦一波?:

    歡迎朋友們關注我的公眾號????:【藍胖子的編程夢】!

    學習容器知識??,性能監控??,Golang?? 相關編程知識

    posted @ 2024-03-13 15:21  藍胖子的編程夢  閱讀(517)  評論(0編輯  收藏  舉報
    免费视频精品一区二区_日韩一区二区三区精品_aaa在线观看免费完整版_世界一级真人片
    <bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>