為什么要主從設置
- 做數據的熱備,作為后備數據庫,主數據庫服務器故障后,可切換到從數據庫繼續工作,避免數據丟失。
- 架構的擴展。業務量越來越大,I/O訪問頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O訪問的頻率,提高單個機器的I/O性能。
- 讀寫分離,使數據庫能支撐更大的並發。在報表中尤其重要。有這么一個情景,有一句sql語句需要鎖表,導致暫時不能使用讀的服務,那么就很影響正在運行中的業務,如果使用主從復制,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。
mysql從3.23版本開始提供復制功能,復制是將主庫的DDL和DML操作通過二進制日志傳遞到復制服務器(從庫)上,然后從庫對這些日志重新執行(重做),從而使得主庫和從庫保持數據一致。
MySQL復制的優點
- 如果主庫出現問題,可以快速切換到從庫提供服務
- 可以在從庫執行查詢操作,降低主庫的訪問壓力。
- 可以在從庫進行備份,以免備份期間影響主庫的服務。
請注意:
- 由於mysql實現的異步復制,所以主庫和從庫數據之間存在一定的差異,在從庫執行查詢操作需要考慮這些數據的差異,一般只有更新不頻繁和對實時性要求不高的數據可以通過從庫查詢,實行要求高的仍要從主庫查詢。
- 如果主從的網絡斷開,則從庫會在網絡恢復正常后,批量進行同步。
- 如果對從庫進行修改數據,那么如果此時從庫正在在執行主庫的bin-log時,則會出現錯誤而停止同步,這個是很危險的操作。所以一般情況下,我們要非常小心的修改從庫上的數據。
MySQL主從復制原理
MySQL主從復制涉及到三個線程,一個運行在主節點(log dump thread),其余兩個(I/O thread, SQL thread)運行在從節點,如下圖所示:
主從復制的三個線程
主節點 binary log dump 線程
當從節點連接主節點時,主節點會創建一個log dump 線程,用於發送bin-log的內容。在讀取bin-log中的操作時,此線程會對主節點上的bin-log加鎖,當讀取完成,甚至在發動給從節點之前,鎖會被釋放。
從節點I/O線程
當從節點上執行start slave命令之后,從節點會創建一個I/O線程用來連接主節點,請求主庫中更新的bin-log。I/O線程接收到主節點binlog dump 進程發來的更新之后,保存在本地relay-log中。
從節點SQL線程
- SQL線程負責讀取relay log中的內容,解析成具體的操作並執行,最終保證主從數據的一致性。
- 對於每一個主從連接,都需要三個進程來完成。當主節點有多個從節點時,主節點會為每一個當前連接的從節點建一個binary log dump 進程,而每個從節點都有自己的I/O進程,SQL進程。從節點用兩個線程將從主庫拉取更新和執行分成獨立的任務,這樣在執行同步數據任務的時候,不會降低讀操作的性能。比如,如果從節點沒有運行,此時I/O進程可以很快從主節點獲取更新,盡管SQL進程還沒有執行。如果在SQL進程執行之前從節點服務停止,至少I/O進程已經從主節點拉取到了最新的變更並且保存在本地relay日志中,當服務再次起來之后,就可以完成數據的同步。
- 要實施復制,首先必須打開Master 端的binary log(bin-log)功能,否則無法實現。
因為整個復制過程實際上就是Slave 從Master 端獲取該日志,然后再在自己身上完全順序的執行日志中所記錄的各種操作。如下圖所示:
復制的基本過程
第一步:從節點上的I/O 進程連接主節點,並請求從指定日志文件的指定位置(或者從最開始的日志)之后的日志內容;
第二步:主節點接收到來自從節點的I/O請求后,通過負責復制的I/O進程根據請求信息讀取指定日志指定位置之后的日志信息,返回給從節點。返回信息中除了日志所包含的信息之外,還包括本次返回的信息的bin-log file 的以及bin-log position;
第三步:從節點的I/O進程接收到內容后,將接收到的日志內容更新到本機的relay log中,並將讀取到的binary log文件名和位置保存到master-info 文件中,以便在下一次讀取的時候能夠清楚的告訴Master“我需要從某個bin-log 的哪個位置開始往后的日志內容,請發給我”;
第四步:Slave 的 SQL線程檢測到relay-log 中新增加了內容后,會將relay-log的內容解析成在主節點上實際執行過的操作,並在本數據庫中執行。
MySQL 主從復制模式
MySQL 主從復制默認是異步的模式。MySQL增刪改操作會全部記錄在binary log中,當slave節點連接master時,會主動從master處獲取最新的bin log文件,並把bin log中的sql relay。
異步模式(mysql async-mode)
異步模式如下圖所示,這種模式下,主節點不會主動push bin log到從節點,這樣有可能導致failover的情況下,也許從節點沒有及時地將最新的bin log同步到本地。
半同步模式(mysql semi-sync)
這種模式下主節點只需要接收到其中一台從節點的返回信息,就會commit;否則需要等待直到超時時間然后切換成異步模式再提交;這樣做的目的可以使主從數據庫的數據延遲縮小,可以提高數據安全性,確保了事務提交后,binlog至少傳輸到了一個從節點上,不能保證從節點將此事務更新到db中。性能上會有一定的降低,響應時間會變長。如下圖所示:
半同步模式不是mysql內置的,從mysql 5.5開始集成,需要master 和slave 安裝插件開啟半同步模式。
全同步模式
全同步模式是指主節點和從節點全部執行了commit並確認才會向客戶端返回成功。
binlog記錄格式
MySQL 主從復制有三種方式:基於SQL語句的復制(statement-based replication,SBR),基於行的復制(row-based replication,RBR),混合模式復制(mixed-based replication,MBR)。對應的binlog文件的格式也有三種:STATEMENT,ROW,MIXED。
1、Statement-base Replication (SBR)就是記錄sql語句在bin log中,Mysql 5.1.4 及之前的版本都是使用的這種復制格式。優點是只需要記錄會修改數據的sql語句到binlog中,減少了binlog日質量,節約I/O,提高性能。缺點是在某些情況下,會導致主從節點中數據不一致(比如sleep(),now()等)。
2、Row-based Relication(RBR) 是mysql master將SQL語句分解為基於Row更改的語句並記錄在bin log中,也就是只記錄哪條數據被修改了,修改成什么樣。優點是不會出現某些特定情況下的存儲過程、或者函數、或者trigger的調用或者觸發無法被正確復制的問題。缺點是會產生大量的日志,尤其是修改table的時候會讓日志暴增,同時增加bin log同步時間。也不能通過bin log解析獲取執行過的sql語句,只能看到發生的data變更。
3、Mixed-format Replication(MBR),MySQL NDB cluster 7.3 和7.4 使用的MBR。是以上兩種模式的混合,對於一般的復制使用STATEMENT模式保存到binlog,對於STATEMENT模式無法復制的操作則使用ROW模式來保存,MySQL會根據執行的SQL語句選擇日志保存方式。
GTID復制模式
在傳統的復制里面,當發生故障,需要主從切換,需要找到binlog和pos點,然后將主節點指向新的主節點,相對來說比較麻煩,也容易出錯。在MySQL 5.6里面,不用再找binlog和pos點,我們只需要知道主節點的ip,端口,以及賬號密碼就行,因為復制是自動的,MySQL會通過內部機制GTID自動找點同步。
多線程復制(基於庫),在MySQL 5.6以前的版本,slave的復制是單線程的。一個事件一個事件的讀取應用。而master是並發寫入的,所以延時是避免不了的。唯一有效的方法是把多個庫放在多台slave,這樣又有點浪費服務器。在MySQL 5.6里面,我們可以把多個表放在多個庫,這樣就可以使用多線程復制。
基於GTID復制實現的工作原理
主節點更新數據時,會在事務前產生GTID,一起記錄到binlog日志中。從節點的I/O線程將變更的bin log,寫入到本地的relay log中。SQL線程從relay log中獲取GTID,然后對比本地binlog是否有記錄(所以MySQL從節點必須要開啟binary log)。如果有記錄,說明該GTID的事務已經執行,從節點會忽略。如果沒有記錄,從節點就會從relay log中執行該GTID的事務,並記錄到bin log。在解析過程中會判斷是否有主鍵,如果沒有就用二級索引,如果有就用全部掃描。
參考: |