<menu id="ycqsw"></menu><nav id="ycqsw"><code id="ycqsw"></code></nav>
<dd id="ycqsw"><menu id="ycqsw"></menu></dd>
  • <nav id="ycqsw"></nav>
    <menu id="ycqsw"><strong id="ycqsw"></strong></menu>
    <xmp id="ycqsw"><nav id="ycqsw"></nav>
  • mysql主從切換步驟(mysql切換主從方法和如何使用)


    MySQL 數據庫內建的復制功能是構建基于 MySQL 的大規模、高性能應用的基礎。復制就是讓一個 MySQL主庫 (Master) 將數據通過日志的方式經網絡傳送到另一臺或多臺 MySQL 從庫(Slave),然后在從庫上重放該日志,以達到和主庫數據同步的目的。

    MySQL 的復制模式分為異步復制、全同步復制及半同步復制三種。下面將針對不同復制模式下的數據一致性問題進行詳細分析。

    異步復制(Asynchronous replication)

    主庫在執行完客戶端提交的事務后會立即提交并返回,不關心從庫是否已經接收到日志并處理。如果此時主庫上已經提交的事務因為某些原因未傳送到從庫,同時主庫發生宕機,且在此時從庫提升為主庫,就會導致新主庫數據缺失,從而造成主從數據不一致的情況發生。該復制模式下必然存在此問題。

    主庫將事務寫入到 Binlog 文件中,并通知 dump 線程發送這些新的 Binlog,然后主庫就會繼續處理提交操作,所以此時無法保證這些 Binlog 已經成功傳到任何一個從庫節點上。

    全同步復制(Fully synchronous replication)

    主庫執行完一個事務,且所有從庫都執行了該事務才返回給客戶端。因為需要等待所有從庫才能返回,所以事務的時間會被拉長,從而性能必然會受到較大影響。

    全同步是在 MySQL NDB Cluster 上采用的復制方式。NDB 是分布式存儲引擎,無共享架構,嚴格來說 NDB 節點不是復制,而是 2PC,確保事務提交的強一致。該集群在國內使用極少,且存在較多問題,不建議采用。全復制會嚴重影響主庫的事務提交性能,對網絡要求非常嚴格,不適合同城、異地的架構場景。

    半同步復制(Semisynchronous replication)

    介于全同步復制與異步復制之間。主庫需要等待至少一個從庫節點收到日志事件,并刷新 Binlog 到 Relay Log 文件中的 ACK 確認消息后,才能提交并返回,主庫一般不需要等待所有從庫的 ACK。注意 :該 ACK 是確保日志傳送到從庫并寫入到中繼日志,而不是從庫已經完成重放、將數據寫入完成。詳見圖 1。

    MySQL 復制一致性問題探索

    image

    圖1 半同步復制模式

    相對于異步復制,半同步復制提高了數據的安全性,同時也帶來了一定程度的延遲,這個延遲最少是一個 TCP/IP 往返的時間。所以,半同步復制最好在低延時的網絡中使用。

    一般在實際生產中,我們把同城或同機房,網絡延遲小的(2ms 內)設置為半同步,對于異地延遲在 10ms 以上的,采用異步復制的方式。

    一般將
    rpl_semi_sync_master_wait_for_slave_count 設置為1,在數據一致性的情況下,可以最大程度保證主庫事務處理的性能。

    MySQL 官方稱該復制模式為無損復制,從復制機制上看,的確會保證數據不丟失。但真實情況是這樣嗎?下面我們從半同步的兩種復制形式進行分析。

    1. 普通半同步 AFTER_COMMIT。處理流程如下(見圖 2)。首先要理解第三步引擎層提交的含義。第三步完成后,由于主庫還未收到從庫返回的確認信息,當前會話一直無法完成并返回給客戶端,但主庫的其他會話已經可以看到執行的結果了。如果按照事務隔離級別來理解,就相當于對主庫的讀取出現了臟讀。

    MySQL 復制一致性問題探索

    image

    圖2 普通半同步處理流程

    例如 :你給小王轉賬 100 元,在步驟三完成后,小王會查詢到自己的余額多了 100 元。但如果此時發生異常 :主庫宕機,日志尚未發送到從庫,且發生了主從切換,從庫提升為主庫。那么因為之前的轉賬 100 元日志未發送到從庫,小王再次查詢余額的時候,會發現之前已“到賬”的 100 元又不見了!

    此時就會出現兩種不一致 :(1)數據層不一致。主庫宕機重啟后,依然有之前轉賬 100 元的記錄,由于從庫未接收到日志,且提升為主庫后無法再同步這部分數據,而原主庫重啟后數據庫會跳過 ACK驗證,引擎層會將事務再次提交,就會比新主庫多一條記錄。(2)應用層不一致。前后看到的結果不一致。

    最致命的是應用層不一致,數據層不一致我們可以通過數據補償或應用重做的方法解決,但應用層不一致就是邏輯錯誤,是不能容忍的!

    2. 增強半同步 AFTER_SYNC。MySQL 從 5.7 版本開始支持增強半同步并設為默認值,處理流程如下(見圖 3)。

    MySQL 復制一致性問題探索

    image

    圖3 增強半同步處理流程

    增強半同步是接收從庫返回 ACK 信息后再做引擎層提交,解決了普通半同步的臟讀、應用層不一致的問題。

    例如 :你給小王轉賬 100 元,在步驟五完成后,小王會查詢到自己的余額多了 100 元。但如果此時發生異常 :主庫宕機,并且發生了主從切換,從庫提升為主庫。由于之前的轉賬 100 元信息已經發送到從庫,那么小王依然可以查看到之前轉賬的 100 元!

    如果在步驟五之前發生異常,由于主庫引擎層未提交,那么其他會話也是無法查看到最新的記錄。

    綜上,就不會出現之前的應用層數據不一致問題,前后看到的結果是一樣的。由此可見,增強半同步才是真正的無損復制,更有效地保證了數據的一致性,確切地說是避免了應用層的不一致。

    那么,增強半同步是不是一定就可以保證數據層和應用層的數據一致性呢?答案是否定的,下面將具體分析。

    (1)第一種情況,日志丟失,主從切換。如果出現主庫日志未同步到從庫或從庫接收后未寫入 Relay Log,且此時發生主從切換就會導致從庫應用日志丟失,出現數據不一致的情況。所以出現主從數據不一致要具備 2 個條件 :主庫日志未同步到從庫 ;同時發生主從切換。

    例如 :應用客戶端向主庫發起一條插入請求,然后開始提交,如果此時網絡中斷,日志未發送到從庫,也就無法接受從庫的 ACK 信息,于是提交無法進行,處于 hang 狀態。這時如果主庫宕機,且同時發生主從切換,那么應用客戶端會出現報錯,記錄未插入成功,新主庫同樣也沒有這條記錄。當應用客戶端連接新主庫后重新發起請求,可再次插入這條記錄,應用邏輯沒有被破壞,數據是一致的。

    但此時會出現數據層的不一致。當原主庫再次啟動后,會跳過 ACK 驗證,對PendingBinlog 進行引擎層面的提交,所以啟動后原主庫就會存在這條記錄,而新主庫并沒有,從而造成數據層的不一致。

    當應用連接新主庫再次執行這條記錄時,新主庫會把這條記錄發送給原主庫,就會報錯(如果是主鍵)或出現重復數據。

    解決方法 :一是重新初始化原主庫數據,然后再建立和新主庫的復制關系。二是手工處理,反向解析原主庫日志,刪除多余的數據 ;新主庫跳過不需要同步的原主庫 GTID 事務號 ;新主庫追平原主庫GTID。三是自動處理,現在有些成熟的管理平臺已經具備了自動處理多余數據并追平 GTID 的功能,操作方法和手工處理的思路是一樣的。

    (2)第二種情況,日志未丟失,主從未切換。主庫因為無法接收到從庫的ACK 信息而無法提交并返回,此時主庫宕機,如果主庫重啟動后未切換,主庫可以正常啟動,那么這條記錄同樣會被提交。而應用層的反應是異常,該條記錄并未成功,那么會出現應用層的不一致。

    解決方法 :一是讓應用確認該記錄已經正常插入,無需重復執行 ;二是數據庫刪除該記錄,應用重新執行。

    主庫等待 ACK 返回的默認時間是60s,超過 60s 會降級成異步并提交事務。有時因為網絡問題從庫一直沒有響應,為了確保主庫可用性,我們會犧牲部分一致性要求,這是符合生產場景的。對一致性要求極高的環境,會將 ACK 返回時間設置為無窮大,這樣雖然保證了一致性,但是會影響部分可用性。

    (3)第三種情況,一主多從,日志丟失。有一種極端情況,即使是增強半同步,也會出現數據層和應用層的數據不一致,見圖 4。

    MySQL 復制一致性問題探索

    image

    圖4 一主多從出現數據不一致的情況

    在一主多從的情況下,將應答從庫數量設置為 1,同城數據中心 A 的從庫首先接收到日志并返回 ACK 給主庫,主庫就可以正常提交。如果數據中心 A 的主庫和從庫均發生宕機,而這此時日志尚未發送給數據庫中心 B、異地數據中心的從庫,并且發生了主從切換,那么這兩個數據中心從庫就會在數據層和應用層均出現和原主庫數據不一致的現象。

    解決方法 :一是增加同城數據中心A 從庫數量(盡量放置在不同機房單元或區域),并增加應答從庫數量。這樣會增加一些成本,而且不能解決數據中心整體故障導致的數據不一致問題。二是增加應答從庫數量。比如一主三從的模式下,將應答從庫數量設為 2,這樣能確保同城 B中心的一個從庫返回 ACK 后才提交,保證了同城 B 中心的數據一致性。但在同城數據中心間網絡不穩定的情況下,對系統性能會有較大影響。對于要求 RPO 嚴格為零的關鍵系統,且兩中心間網絡安全可靠的前提下,可以采取這種方法,其他系統不必要采用。三是將同城雙中心擴展為同城三中心或多中心,同時增加應答從庫數量。這是最佳方式,但成本過高,具備此條件的數據中心可以采用。

    總 結

    究竟該如何最大程度地避免數據不一致的發生呢?總結如下 :一是采用較高版本的 MySQL 數據庫產品,至少在 5.7及以上版本,啟用增強半同步。二是回退掉 PendingBinlog,采用雙 1 參數,ROW格式,開啟 GTID。三是使用第三方插件如 MHA、keepalived 設置主庫切換策略,發生宕機后不馬上切換,嘗試 N 次重啟后再切換,另外從庫提升為主庫后,嘗試從原主庫拉取日志補齊(系統正常,MySQL 數據庫無法啟動的情況)。四是建立自動切換工具,啟用數據校驗和補齊機制。五是條件允許的情況下,增加數據中心數量、從庫數量,增加應答從庫數量。

    最后,附上我行某信息系統的一個實際案例(見圖 5),供讀者參考。數據庫版本為MySQL 5.7,主要采用了以下措施:一是采用了一主三從模式,同城雙數據中心,其中一個主庫和一個從庫在同城 A機房,另兩個從庫在同城 B 機房。二是采用了增強半同步,由于系統 RPO 接近但可不為零,故應答從庫數量設置為 1。三是完備的切換策略,主庫嘗試 N 次(N分鐘)啟動后再切換,基于自定義權重和最新 GTID 進行選主。四是數據校驗和補齊機制功能,切換后,備選主庫校驗發現還有未同步的 Binlog,會嘗試從原主庫獲取最新的 Binlog 日志并應用。

    MySQL 復制一致性問題探索

    image

    版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。

    發表評論

    登錄后才能評論
    国产精品区一区二区免费