https://www.cnblogs.com/cnmenglang/p/6393769.html
MySQL的主從同步是一個很成熟的架構,優點為:①在從服務器可以執行查詢工作(即我們常說的讀功能),降低主服務器壓力;②在從主服務器進行備份,避免備份期間影響主服務器服務;③當主服務器出現問題時,可以切換到從服務器。
相信大家對於這些好處已經非常了解了,在項目的部署中也采用這種方案。但是MySQL的主從同步一直有從庫延遲的問題,那么為什么會有這種問題。這種問題如何解決呢?
1. MySQL數據庫主從同步延遲原理。
2. MySQL數據庫主從同步延遲是怎么產生的。
3. MySQL數據庫主從同步延遲解決方案。
1. MySQL數據庫主從同步延遲原理。
答:談到MySQL數據庫主從同步延遲原理,得從mysql的數據庫主從復制原理說起,mysql的主從復制都是單線程的操作,主庫對所有DDL和 DML產生binlog,binlog是順序寫,所以效率很高,slave的Slave_IO_Running線程到主庫取日志,效率很比較高,下一步, 問題來了,slave的Slave_SQL_Running線程將主庫的DDL和DML操作在slave實施。DML和DDL的IO操作是隨即的,不是順 序的,成本高很多,還可能可slave上的其他查詢產生lock爭用,由於Slave_SQL_Running也是單線程的,所以一個DDL卡主了,需要 執行10分鍾,那么所有之后的DDL會等待這個DDL執行完才會繼續執行,這就導致了延時。有朋友會問:“主庫上那個相同的DDL也需要執行10分,為什 么slave會延時?”,答案是master可以並發,Slave_SQL_Running線程卻不可以。
2. MySQL數據庫主從同步延遲是怎么產生的。
答:當主庫的TPS並發較高時,產生的DDL數量超過slave一個sql線程所能承受的范圍,那么延時就產生了,當然還有就是可能與slave的大型query語句產生了鎖等待。
3. MySQL數據庫主從同步延遲解決方案
答:最簡單的減少slave同步延時的方案就是在架構上做優化,盡量讓主庫的DDL快速執行。還有就是主庫是寫,對數據安全性較高,比如 sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之類的設置,而slave則不需要這么高的數據安全,完全可以講sync_binlog設置為0或者關閉binlog,innodb_flushlog也 可以設置為0來提高sql的執行效率。另外就是使用比主庫更好的硬件設備作為slave。
附加:
sync_binlog 配置說明:
sync_binlog”:這個參數是對於MySQL系統來說是至關重要的,他不僅影響到Binlog對MySQL所帶來的性能損耗,而且還影響到MySQL中數據的完整性。對於“sync_binlog”參數的各種設置的說明如下:
sync_binlog=0,當事務提交之后,MySQL不做fsync之類的磁盤同步指令刷新binlog_cache中的信息到磁盤,而讓Filesystem自行決定什么時候來做同步,或者cache滿了之后才同步到磁盤。
sync_binlog=n,當每進行n次事務提交之后,MySQL將進行一次fsync之類的磁盤同步指令來將binlog_cache中的數據強制寫入磁盤。
在MySQL中系統默認的設置是sync_binlog=0,也就是不做任何強制性的磁盤刷新指令,這時候的性能是最好的,但是風險也是最大的。因為一旦系統Crash,在binlog_cache中的所有binlog信息都會被丟失。而當設置為“1”的時候,是最安全但是性能損耗最大的設置。因為當設置為1的時候,即使系統Crash,也最多丟失binlog_cache中未完成的一個事務,對實際數據沒有任何實質性影響。
從以往經驗和相關測試來看,對於高並發事務的系統來說,“sync_binlog”設置為0和設置為1的系統寫入性能差距可能高達5倍甚至更多。
innodb_flush_log_at_trx_commit 配置說明:
默認值1的意思是每一次事務提交或事務外的指令都需要把日志寫入(flush)硬盤,這是很費時的。特別是使用電 池供電緩存(Battery backed up cache)時。設成2對於很多運用,特別是從MyISAM表轉過來的是可以的,它的意思是不寫入硬盤而是寫入系統緩存。日志仍然會每秒flush到硬 盤,所以你一般不會丟失超過1-2秒的更新。設成0會更快一點,但安全方面比較差,即使MySQL掛了也可能會丟失事務的數據。而值2只會在整個操作系統 掛了時才可能丟數據。
mysql-5.6.3已經支持了多線程的主從復制。原理和丁奇的類似,丁奇的是以表做多線程,Oracle使用的是以數據庫(schema)為單位做多線程,不同的庫可以使用不同的復制線程。
基於局域網的master/slave機制在通常情況下已經可以滿足'實時'備份的要求了。如果延遲比較大,就先確認以下幾個因素:
1. 網絡延遲
2. master負載
3. slave負載
一般的做法是,使用多台slave來分攤讀請求,再從這些slave中取一台專用的服務器,只作為備份用,不進行其他任何操作,就能相對最大限度地達到'實時'的要求了
slave_net_timeout單位為秒 默認設置為 3600秒
參數含義:當slave從主數據庫讀取log數據失敗后,等待多久重新建立連接並獲取數據
master-connect-retry單位為秒 默認設置為 60秒
參數含義:當重新建立主從連接時,如果連接建立失敗,間隔多久后重試。
通常配置以上2個參數可以減少網絡問題導致的主從數據同步延遲
判斷主從延時,通常有兩個方法:
1. Seconds_Behind_Master vs 2. mk-heartbeat,下面具體說下兩者在實現功能的差別。
可以通過監控show slave status\G命令輸出的Seconds_Behind_Master參數的值來判斷,是否有發生主從延時。
其值有這么幾種:
NULL - 表示io_thread或是sql_thread有任何一個發生故障,也就是該線程的Running狀態是No,而非Yes.
0 - 該值為零,是我們極為渴望看到的情況,表示主從復制良好,可以認為lag不存在。
正值 - 表示主從已經出現延時,數字越大表示從庫落后主庫越多。
負值 - 幾乎很少見,只是聽一些資深的DBA說見過,其實,這是一個BUG值,該參數是不支持負值的,也就是不應該出現。
Seconds_Behind_Master是通過比較sql_thread執行的event的timestamp和io_thread復制好的 event的timestamp(簡寫為ts)進行比較,而得到的這么一個差值。我們都知道的relay-log和主庫的bin-log里面的內容完全一 樣,在記錄sql語句的同時會被記錄上當時的ts,所以比較參考的值來自於binlog,其實主從沒有必要與NTP進行同步,也就是說無需保證主從時鍾的 一致。你也會發現,其實比較真正是發生在io_thread與sql_thread之間,而io_thread才真正與主庫有關聯,於是,問題就出來了, 當主庫I/O負載很大或是網絡阻塞,io_thread不能及時復制binlog(沒有中斷,也在復制),而sql_thread一直都能跟上 io_thread的腳本,這時Seconds_Behind_Master的值是0,也就是我們認為的無延時,但是,實際上不是,你懂得。這也就是為什 么大家要批判用這個參數來監控數據庫是否發生延時不准的原因,但是這個值並不是總是不准,如果當io_thread與master網絡很好的情況下,那么 該值也是很有價值的。(就好比:媽–兒子–媳婦的關系,媽與兒子親人,媳婦和兒子也親人,不見得媳婦與媽就很親。開個玩笑:-)之前,提到 Seconds_Behind_Master這個參數會有負值出現,我們已經知道該值是io_thread的最近跟新的ts與sql_thread執行到 的ts差值,前者始終是大於后者的,唯一的肯能就是某個event的ts發生了錯誤,比之前的小了,那么當這種情況發生時,負值出現就成為可能。
方法2. mk-heartbeat,Maatkit萬能工具包中的一個工具,被認為可以准確判斷復制延時的方法。
mk-heartbeat的實現也是借助timestmp的比較實現的,它首先需要保證主從服務器必須要保持一致,通過與相同的一個NTP server同步時鍾。它需要在主庫上創建一個heartbeat的表,里面至少有id與ts兩個字段,id為server_id,ts就是當前的時間戳 now(),該結構也會被復制到從庫上,表建好以后,會在主庫上以后台進程的模式去執行一行更新操作的命令,定期去向表中的插入數據,這個周期默認為1 秒,同時從庫也會在后台執行一個監控命令,與主庫保持一致的周期去比較,復制過來記錄的ts值與主庫上的同一條ts值,差值為0表示無延時,差值越大表示 延時的秒數越多。我們都知道復制是異步的ts不肯完全一致,所以該工具允許半秒的差距,在這之內的差異都可忽略認為無延時。這個工具就是通過實打實的復 制,巧妙的借用timestamp來檢查延時,贊一個!
===============================================
由於歷史原因,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 - 該值為零,是我們極為渴望看到的情況,表示主從復制狀態正常
其它的方法我也沒試過, 暫時不做評論
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內容請查看下面相關鏈接