1. 程式人生 > 資料庫 >MySQL主從同步延遲的原因及解決辦法

MySQL主從同步延遲的原因及解決辦法

由於歷史原因,MySQL複製基於邏輯的二進位制日誌,而非重做日誌。多次被問到何時MySQL能支援基於物理的複製,其實這就看MySQL各位大佬的想法。上次和賴老師腦暴,倏地說道:MySQL會不會來個基於Paxos的redo複製?

物理複製的真正好處不在於正確性,因為基於ROW格式的日誌複製也已能完全保證複製的正確性。由於物理日誌的寫入是在事務執行過程中就不斷寫入,而二進位制日誌的寫入僅僅在事務提交時。因此物理日誌的優勢如下所示:

  • 複製架構下,大事務日誌提交速度快;
  • 複製架構下,主從資料延遲小;

假設執行了1個小時的某大事務,在最後提交時,只需寫入最後提交部分的重做日誌(redo log可視為物理日誌)。雖然此大事務重做日誌寫入的總量可能有1G,然而在提交時,資料主從複製僅需將最後一部分日誌傳輸到遠端從機,因為之前的重做日誌已經在執行的1個小時內不斷地同步到從機。

對於二進位制日誌,由於其寫入時間發生在事務提交時,因此假設產生了1G的二進位制日誌,則需要事務提交時間會包含這1G日誌的寫入時間。在Oracle中有一種說法,事務的提交速度都是平的,不論事務的大小。這在MySQL資料庫中是不成立的。即,MySQL的提交速度取決於事務產生的二進位制日誌的大小,事務提交的速度不是平的。

更為糟糕的是,MySQL主從複製在大事務下的延遲。同樣假設1個大事務在主伺服器上執行了1個小時,則需要在最後的提交時間傳送到從伺服器。主從延遲的時間至少為1個小時,若從伺服器執行還需1個小時,則主從複製延遲的最壞情況可能是2個小時。物理複製則不存在這樣的限制,原因還是如前所述,事務提交過程中,日誌已經在傳輸和回放。

物理複製雖好,但是也有自己的缺陷,就我自己的實際體驗來看:

  • 物理複製下,主機壞塊會導致主從伺服器都無法啟動;相信遇到過此問題的同學不在少數;
  • 此外,做ETL是有困難的,比如怎麼將物理日誌同步到Hadoop大資料平臺呢?

一言以蔽之,對於MySQL資料庫來說,任何時刻不允許有大事務執行。若要執行,則將大事務拆成一個個小的子事務來執行。這是最基本心法口訣,但卻又和Oracle有著很大不同。總之,氣宗、劍宗,本無好壞,學會理解其中的差異,融會貫通方可達風清揚般的致臻境界。

mysql 用主從同步的方法進行讀寫分離,減輕主伺服器的壓力的做法現在在業內做的非常普遍。 主從同步基本上能做到實時同步。我從別的網站借用了主從同步的原理圖。

在配置好了, 主從同步以後, 主伺服器會把更新語句寫入binlog,從伺服器的IO 執行緒(這裡要注意, 5.6.3 之前的IO執行緒僅有一個,5.6.3之後的有多執行緒去讀了,速度自然也就加快了)回去讀取主伺服器的binlog 並且寫到從伺服器的Relay log 裡面,然後從伺服器的 的SQL thread 會一個一個執行 relay log 裡面的sql , 進行資料恢復。

relay 就是 傳遞,relay race 就是接力賽的意思

1. 主從同步的延遲的原因

我們知道, 一個伺服器開放N個連結給客戶端來連線的, 這樣有會有大併發的更新操作,但是從伺服器的裡面讀取binlog 的執行緒僅有一個, 當某個SQL在從伺服器上執行的時間稍長 或者由於某個SQL要進行鎖表就會導致,主伺服器的SQL大量積壓,未被同步到從伺服器裡。這就導致了主從不一致, 也就是主從延遲。

2. 主從同步延遲的解決辦法

實際上主從同步延遲根本沒有什麼一招制敵的辦法, 因為所有的SQL必須都要在從伺服器裡面執行一遍,但是主伺服器如果不斷的有更新操作源源不斷的寫入, 那麼一旦有延遲產生, 那麼延遲加重的可能性就會原來越大。 當然我們可以做一些緩解的措施。

  • a. 我們知道因為主伺服器要負責更新操作, 他對安全性的要求比從伺服器高, 所有有些設定可以修改,比如sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之類的設定,而slave則不需要這麼高的資料安全,完全可以講sync_binlog設定為0或者關閉binlog,innodb_flushlog, innodb_flush_log_at_trx_commit也 可以設定為0來提高sql的執行效率 這個能很大程度上提高效率。另外就是使用比主庫更好的硬體裝置作為slave。
  • b. 就是把,一臺從伺服器當度作為備份使用, 而不提供查詢, 那邊他的負載下來了, 執行relay log 裡面的SQL效率自然就高了。
  • c. 增加從伺服器嘍,這個目的還是分散讀的壓力, 從而降低伺服器負載。

3. 判斷主從延遲的方法

MySQL提供了從伺服器狀態命令,可以通過 show slave status 進行檢視, 比如可以看看Seconds_Behind_Master引數的值來判斷,是否有發生主從延時。

其值有這麼幾種:

NULL - 表示io_thread或是sql_thread有任何一個發生故障,也就是該執行緒的Running狀態是No,而非Yes.
0 - 該值為零,是我們極為渴望看到的情況,表示主從複製狀態正常

其它的方法我也沒試過, 暫時不做評論

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支援。如果你想了解更多相關內容請檢視下面相關連結