MySQL數據庫複製概論

每當咱們討論一項(新的)領域技術的時候,最好的方式一般是首先拋出一些問題,這些問題大體分爲三類:誒?這項技術又是什麼玩意(What)?這項技術爲何會存在?咱們已經有那麼多解決方案(Method)了,咱們問什麼要用它(Why)?若是這項技術那麼好且咱們正好有場景能夠用到這項技術,且能使咱們的系統獲得很樂觀的優化,那麼咱們怎麼用呢(How)?大概已經有同窗以爲這些問題很熟悉了,是的,這就是黃金全法則提出的三個問題,對於每種新鮮事物咱們首先基於這三個問題去了解,更有利於弄清楚事情的本質,端正態度去了解,而不是由於新,由於你們都說好,纔要去了解……。說了那麼多前奏,咱們能夠開始了,今天咱們就帶着黃金圈法則提出的三個問題去看看MySQL數據庫複製這項領域技術,而後再結合實際應用擴展一些問題,本文也僅僅是結合本身瞭解的皮毛以拋磚引玉的態度和你們一塊兒分享。sql


WHAT?數據庫

MySQL複製使得一臺Mysql數據庫服務器的數據被拷貝到其餘一臺或者多臺數據庫服務器,前者一般被叫作Master,後者一般被叫作Slave。服務器

MySQL複製示意圖網絡

複製的結果是集羣(Cluster)中的全部數據庫服務器獲得的數據理論上都是同樣的,都是同一份數據,只是有多個copy。MySQL默認內建的複製策略是異步的,基於不一樣的配置,Slave不必定要一直和Master保持鏈接不斷的複製或等待複製,咱們指定複製全部的數據庫,一部分數據庫,甚至是某個數據庫的某部分的表。併發

MySQL複製支持多種不一樣的複製策略,包括同步、半同步、異步和延遲策略等。異步

  1. 同步策略:Master要等待全部Slave應答以後纔會提交(MySql對DB操做的提交一般是先對操做事件進行二進制日誌文件寫入而後再進行提交)。
    ide

  2. 半同步策略:Master等待至少一個Slave應答就能夠提交。性能

  3. 異步策略:Master不須要等待Slave應答就能夠提交。優化

  4. 延遲策略:Slave要至少落後Master指定的時間。
    spa

MySQL複製同時支持多種不一樣的複製模式:

  1. 基於語句的複製,Statement Based Replication(SBR)。

  2. 基於行的複製Row Based Replication(RBR)。

  3. 混合複製(Mixed)。


WHY?

這個問題其實也就是MySQL複製有什麼好處,咱們能夠將複製的好處歸結於下面幾類:

  1. 性能方面:MySQL複製是一種Scale-out方案,也即「水平擴展」,將原來的單點負載擴散到多臺Slave機器中去,從而提升整體的服務性能。在這種方式下,全部的寫操做,固然包括UPDATE操做,都要發生在Master服務器上。讀操做發生在一臺或者多臺Slave機器上。這種模型能夠在必定程度上提升整體的服務性能,Master服務器專一於寫和更新操做,Slave服務器專一於讀操做,咱們同時能夠經過增長Slave服務器的數量來提升讀服務的性能。

  2. 防腐化:因爲數據被複制到了Slave,Slave能夠暫停複製進程,進行數據備份,所以能夠防止數據腐化。

  3. 故障恢復:同時多臺Slave若是有一臺Slave掛掉以後咱們還能夠從其餘Slave讀取,若是配置了主從切換的話,當Master掛掉以後咱們還能夠選擇一臺Slave做爲Master繼續提供寫服務,這大大增長了應用的可靠性。

  4. 數據分析:實時數據能夠存儲在Master,而數據分析能夠從Slave讀取,這樣不會影響Master的性能。


HOW?

這裏咱們只介紹一下MySQL的複製是如何工做的,至於配置,網上也有不少相關的介紹,讀者具體應用的時候能夠再去查閱。咱們拿最經常使用的基於二進制文件的複製來看看。

MySQL複製工做示意圖

MySQL的複製過程大概以下:

首先,主庫在每次準備提交事務完成數據更新操做以前都會將數據更改操做記錄到二進制日誌中,這些日誌是以二進制的方式記錄數據更改的事件。值得一提的是二進制日誌中記錄的順序其實是事務的提交順序,而非SQL執行語句的順序。在記錄二進制日誌以後,主庫會告訴存儲引擎事務能夠提交了。

而後,備庫會啓動一個IO線程,之因此叫作IO線程是由於這個線程專門作IO相關的工做,包括和主庫創建鏈接,而後在主庫上啓動一個特殊的二進制轉儲線程,這個轉儲線程會不斷的讀取二進制日誌中的事件,發送給備庫的IO線程,備庫的IO線程會將事件記錄到中繼日誌中。

備庫會有一個叫作SQL的線程被開啓,這個線程作的事情是讀取中繼日誌中的DB操做事件在備庫執行,從而實現數據更新。

總的來講,在發生複製的主庫服務器和備庫服務器中,一共有三個線程在工做。


上面咱們已經大概瞭解的什麼是複製?爲何要複製?如何複製?這三個問題了,接下來咱們基於上面的介紹,提出一些實際應用可能會發生的問題來思考如何解決。博主自問自答的方式-。-


問答環節

問題一:經過複製模型雖然讀能力能夠經過擴展slave機器來達到提升,而寫能力卻不能,若是寫達到瓶頸咱們應該怎麼作呢?

答:咱們首先會得出結論,這種複製模型對於寫少讀多型應用是很是有優點的,其次,當遇到這種問題的時候咱們能夠對數據庫進行分庫操做,所謂分庫,就是將業務相關性比較大的表放在同一個數據庫中,例如以前數據庫有A,B,C,D四張表,A表和B表關係比較大,而C表和D表關係比較大,這樣咱們把C表和D表分離出去成爲一個單獨的數據庫,經過這種方式,咱們能夠將原有的單點寫變成雙點寫或多點些,從而下降原有主庫的寫負載。


問題二:由於複製是有延遲的,確定會發生主庫寫了,可是從庫尚未讀到的狀況,遇到這種問題怎麼辦?

答:MySQL支持不一樣的複製策略,基於不一樣的複製策略達到的效果也是不同的,若是是異步複製,MySQL不能保證從庫立馬可以讀到主庫實時寫入的數據,這個時候咱們要權衡選擇不一樣複製策略的利弊來進行取捨。所謂利弊,就是咱們是否對從庫的讀有那麼高的實時性要求,若是真的有,咱們能夠考慮使用同步複製策略,可是這種策略相比於異步複製策略會大大下降主庫的響應時間和性能。咱們是否能夠在應用的設計層面去避開這個問題?


問題三:複製的不一樣模式有什麼優缺點?咱們如何選擇?

答:基於語句的複製其實是把主庫上執行的SQL在從庫上從新執行一遍,這麼作的好處是實現起來簡單,當前也有缺點,好比咱們SQL裏面使用了NOW(),當同一條SQL在從庫中執行的時候顯然和在主庫中執行的結果是不同的,注入此類問題能夠類推。其次問題就是這種複製必須是串行的,爲了保證串行執行,就須要更多的鎖。

基於行的複製的時候二進制日誌中記錄的其實是數據自己,這樣從庫能夠獲得正確的數據,這種方式缺點很明顯,數據必需要存儲在二進制日誌文件中,這無疑增長的二進制日誌文件的大小,同時增長的IO線程的負載和網絡帶寬消耗。而相比於基於語句的複製還有一個優勢就是基於行的複製無需重放查詢,省去了不少性能消耗。

不管哪一種複製模式都不是完美的,日誌如何選擇,這個問題能夠在理解他們的優缺點以後進行權衡。


問題四:複製的工做過程只有三個線程來完成,對於Master來講,寫是併發的,也就出現了一個IO線程要把全部併發的數據變動事件記錄,這個IO線程會不會累死?當一個Master對應多個Slave的時候,其實在Master中會喚起多個IO線程,這無疑會增長Master的資源開銷,若是出現事件堆積,也就是事件太多,來不及及時發送出去怎麼辦?另外就是Slave那邊的IO線程和SQL線程也會有對應主庫併發數據變動事件,而Slave方單個線程處理的問題,這個時候Slave線程會不會累死?

答:上面的問題確實會發生,上面第一個問題和第二個問題實際上是寫負載的問題,當事件堆積太多,從庫時延就會變大,Slave單SQL線程問題聽說有參數能夠開啓並行操做,這個你們能夠確認一下。


問題五:針對複製工做過程可能會出現的問題,主庫寫完二進制日誌文件同時都會保存二進制日誌的偏移量,可是當斷電的時候,二進制日誌文件沒有刷新到磁盤,主庫從新啓動以後,從庫嘗試讀該偏移量的二進制日誌,會出現讀不到的狀況,這個問題應該怎麼解決?

答:首先若是開啓了sync_binlog選項,對於innodb同時設置innodb_flush_log_at_trx_commot=1,則能夠保證二進制日誌文件會被寫入磁盤,但MyISAM引擎可能會致使數據損壞。若是沒有開啓這個選項,則能夠經過制定從庫的二進制偏移量爲下一個二進制日誌文件的開頭,可是不能解決事件丟失問題。


問題六:從庫在非計劃的關閉或重啓時,回去讀master.info文件去找上次中止複製的位置,這一樣會有一個問題,若是master.info不正確,就會致使複製數據不一致的狀況,遇到這個問題怎麼辦?

答:這個問題能夠經過兩種方式解決,一是控制master.info在從庫非計劃關閉或重啓的時候讓master.info可以同步到磁盤,這樣下次啓動的時候就不會讀取錯誤的信息,這有助於減小錯誤的發生機率。另外想要找到正確的複製位置是困難的,咱們也能夠選擇忽略錯誤。


……


其實問題也是蠻多的,這裏就再也不繼續提問了,包括若是主庫二進制日誌文件損壞怎麼辦?從庫中繼日誌文件損壞怎麼辦?由於每一個環節都不是百分之一百可靠的,所以咱們必須對可能遇到的問題提出假設,思考解決方案。本文經過黃金圈法則提出的三個問題來認識MySQL複製,經過自問自答的形式來對主體的一些可能存在的應用問題進行討論,對於複製方面還存在不少的實際應用問題,這裏只是拋磚引玉,還請數據庫大牛們多多指教。

相關文章
相關標籤/搜索