快速導航
- 一、主從復制到底是啥
- 1、一張圖程序
- 2、新的備庫與主庫同步方法
- 3、復制配置
- 二、主從復制有什么用
- 1、資料備份
- 2、負載均衡
- 3、高可用性和故障切換
- 4、MySQL升級測驗
- 三、復制原理有2個
- 1、基于陳述句的復制:
- 2、基于行的復制:
- 3、Mysql權衡動態切換
- 4、statement和row模式的區別
- 四、Mysql主從同步延遲分析及解決方案
- 1、主從復制存在的問題
- 2、延遲原因
- 3、主從延時排查方法
- 4、解決方案
- 五、總結
資料的復制作為高可用、可擴展和備份的基礎,目前的各種資料庫幾乎都有復制這項功能,最終目的就是備份資料,以防資料丟失造成重大損失,
MySQL的主從復制就是一個典型的方案,實作一個主庫的資料復制到一個或多個備庫,這個方案屬于“水平擴展”的架構,
這篇文章將帶大家學習整個MySQL主從復制的內容,比如現在你會提問:MySQL是怎么實作主從復制的?主從復制有什么用?怎么保證主庫和備庫的同步復制,資料一致性?如果出現網路延遲等原因,查詢資料不一致怎么辦?
這些問題也是在面試中經常會問到的,接下來會詳細分析,完整清晰,建議收藏!
一、主從復制到底是啥
1、主庫上把資料更新記錄寫進二進制日志(Binary Log),簡稱binlog,
2、備庫將主庫的日志復制到自己的中繼日志(Relay Log)中,
3、備庫讀取中繼日志的事件,將其重放到備庫資料之上,
1、一張圖程序
下圖是MySQL主從復制作業細節,

- 首先,備庫會啟動一個I/O執行緒,跟主庫建立一個普通的客戶端連接,將主庫的binlog復制到本地的中繼日志,
- 然后主庫啟動一個binlog dump執行緒,讀取主庫上binlog事件,且不會對事件進行輪詢,如果執行緒讀取完最新的更新事件,則進入睡眠,直到主庫發送信號量通知有新事件產生才被喚醒,備庫I/O執行緒會將收到的事件記錄到本地log,
- 備庫SQL執行緒執行最后一步,讀取Relay Log日志并執行資料更新,
主庫上記錄二進制日志,每次準備提交事務完成資料個更新之前,主庫將資料更新事件寫進binlog,
Mysql按事務提交的順序而非每條陳述句的執行順序記錄binlog,完成記錄后,主庫告訴存盤引擎可以提交事務,
復制架構實作了獲取事件和重放事件的解耦,兩個程序異步執行,也看得出,備庫重放事件是SQL執行緒的單執行緒執行,
2、新的備庫與主庫同步方法
前面的整個主從復制程序,是假設主備庫都是默認剛安裝好的情況,兩臺服務器上的資料相同,而大多數情況,我們的主庫是運行一段時間了,然后將一臺新的服務器資料庫跟主庫進行同步,
這樣,有3種方法來初始化新的備庫,
1、從主庫復制
2、從另一臺備庫克隆資料
3、使用最近一次備份啟動備庫
因為初始時主備庫資料不同步,需要有3個條件使得主庫和備庫保持同步,
1、在某個時間點的主庫的資料快照,
2、主庫當前二進制日志檔案和獲得資料快照時在該binlog中的偏移量,通過這兩個坐標確定二進制日志檔案的位置,
3、從快照時間到現在的binlog,
下面幾種備份方式可以實作資料克隆,
- 冷備份
關閉主庫,把資料復制到備庫,重啟主庫后,會使用新的binlog日志檔案,缺點很明顯,關閉主庫,通常是實作高可用性,這種方案不推薦, - 熱備份
僅僅使用MyISAM表時,可以在主庫運行時使用mysqlhotcopy或rsync來復制資料;
只包含InnoDB表時,可以使用以下命令來轉儲主庫資料并將其加載到備庫,
mysqldump --single-transaction --all-databases --master-data = 1 --host = serverName | mysql --host = seeverName2
--single-transaction使得轉儲的資料是事務開始前的資料,
3.快照
根據二進制日志坐標,使用主庫的快照來初始化備庫,然后使用change master to指定二進制日志的坐標,
- 熱備份工具Percona Xtrabackup
使用開源工具也是比較好的選擇,可以在不阻塞服務器的情況下克隆主庫來建立備庫,
3、復制配置
在主庫上的binlog最重要的選項是sync_binlog = 1表示每次提交事務前會將日志同步到磁盤,保證崩潰時不會丟失資料,而在備庫,設定為0來減少不必要的開銷,
MySQL5.5可以選擇控制崩潰時將事件重繪到磁盤,配置如下:
sync_master_info = 1
sync_relay_log = 1
sync_relay_log_info = 1
二、主從復制有什么用
1、資料備份
很明顯,第一個想到的就是作資料備份,MySQL復制不會對帶寬造成很大的壓力,即使有網路延遲,復制作業仍然可以進行,
2、負載均衡
主從服務器都可以分攤讀操作,在讀密集型的應用,可以通過負載均衡將操作分布到不同服務器上,
3、高可用性和故障切換
復制能幫助避免MySQL單點失敗,作為實作高可用的基礎,
4、MySQL升級測驗
使用一個高版本MySQL作為備庫,保證升級全部資料庫之前,查詢能夠在備庫執行,
三、復制原理有2個
前面介紹了MySQL復制的大致程序,現在已經對復制由一個整體的理解,接下來就是具體內部實作復制的細節了,
復制主要由兩種模式:基于陳述句的復制模式、基于行的復制模式;還有一個同時使用兩種模式的混合模式,
我總結下來,不同的模式的原理和優缺點如下,
1、基于陳述句的復制:
binlog_format = statement
該模式下,主庫會記錄造成資料更改的陳述句,當備庫讀取并重放這些事件時,只需要把這些SQL再執行一遍,
優點:實作簡單,只需要簡單記錄和執行這些陳述句,二進制日志檔案更加緊湊,占用較小帶寬,
缺點:傳輸二進制日志時,額外要記錄當前時間戳,但可能無法正確復制SQL,比如CURRENT_USER()函式、存盤程序和觸發器在使用該模式也會出現問題,備庫更新只能串行,
2、基于行的復制:
binlog_format = row
該模式下會將實際資料記錄在二進制日志中,
優點:無須重放更新主庫資料的查詢,可以更高效地復制資料,占用更少的CPU,
缺點: 做全表更新時,復制開銷會很大,因為每一行資料都會被記錄到二進制日志,檔案非常龐大,并且會主庫上記錄日志和復制增加額外的負載,更慢的日志記錄則會降低并發度,
3、Mysql權衡動態切換
binlog_format = mixed
默認使用基于陳述句的復制方式,如果陳述句無法正確復制,就切換基于行的復制模式,
以上模式通過設定會話級別的變數binlog_format來控制二進制日志格式,
4、statement和row模式的區別
1、基于row復制模式
存盤程序、函式、觸發器,都是將執行之后的資料行,傳給slave,
2、在基于statement 的復制時,存盤程序、函式、觸發器可能會資料不一致的情況
存盤程序和函式在定義時,有 確定性函式和非確定性函式的,比如uuid(),now()這些函式都是非確定性函式,因為它們每次執行的值是不確定的,
在master和slave上分別執行會導致資料不一致,所以在基于陳述句復制的環境中,函式都必須是確定性的,否則只能采用row復制格式,
四、Mysql主從同步延遲分析及解決方案
這就是開頭所講的如何保證主從復制資料的一致性,大多數情況,受網路延遲、服務器性能等影響,會存在一些不理想的情況,
1、主從復制存在的問題
主庫宕機后,資料可能丟失;
主從同步延遲,
2、延遲原因
MySQL主庫對所有DDL和DML產生的日志寫進binlog,由于binlog是順序寫,所以效率很高,
而備庫SQL執行緒復制都是單執行緒的操作,當主庫的并發較高時,產生的DML數量超過slave的SQL Thread所能處理的速度,或者當slave中有大型query陳述句產生了鎖等待那么延時就產生了,
原因總結為這幾個:
Master負載過高、Slave負載過高、網路延遲、機器性能太低、MySQL配置不合理,
3、主從延時排查方法
通過監控show slave status 命令輸出的Seconds_Behind_Master引數的值來判斷:
- NULL,表示io_thread或是sql_thread有任何一個發生故障;
- 該值為零,表示主從復制良好;
- 正值,表示主從已經出現延時,數字越大表示從庫延遲越嚴重,
MySQL并沒有內建的方法來比較兩臺服務器的資料是否相同,所以需要使用第三方工具Percona Toolkit,其中pt-table-checksum命令可以確認主備資料是否一致,
其作業原理就是在主庫執行insert ... select查詢,將結果插入一個表,傳遞到備庫,備庫執行一遍后將結果進行比較,這種方法能夠與復制作業同時進行,
pt-table-checksum --replicate = test.checksum <master_host>
4、解決方案
- 半同步復制
從MySQL5.5開始,MySQL已經支持半同步復制了,半同步復制介于異步復制和同步復制之間,主庫在執行完事務后不立刻回傳結果給客戶端,需要等待至少一個從庫接收到并寫到relay log中才回傳結果給客戶端,相對于異步復制,半同步復制提高了資料的安全性,同時它也造成了一個TCP/IP往返耗時的延遲,
- 主庫配置
sync_binlog = 1,innodb_flush_log_at_trx_commit = 1
sync_binlog的默認值是0,MySQL不會將binlog同步到磁盤,其值表示每寫多少binlog同步一次磁盤,備庫配置值為零,
innodb_flush_log_at_trx_commit = 1表示每一次事務提交或事務外的指令都需要把日志flush到磁盤,
注意:將以上兩個值同時設定為1時,寫入性能會受到一定限制,只有對資料安全性要求很高的場景才建議使用,比如涉及到錢的訂單支付業務,而且系統I/O能力必須可以支撐!
另外,還有幾個方法,
- 優化網路
- 升級Slave硬體配置
- 升級MySQL版本到5.7,使用并行復制
五、總結
本文主要介紹了MySQL主從復制,認真看完這篇文章將會對主從復制有一個比較系統的理解,其他資料庫相關原理也是類似架構,這篇作為基礎可以掌握,復制原理基礎知識已經完全足夠,
MySQL是怎么實作主從復制的?主從復制有什么用?怎么保證主庫和備庫的同步復制,資料一致性?如果出現網路延遲等原因,查詢資料不一致怎么辦?
這些問題是否能回答了呢?
歡迎大佬們討論指點~
那本篇文章就介紹到這里了,面試必問系列,記得收藏~
本篇內容首發我的CSDN博客:半萬字長文學習《MySQL》主從復制原理,面試必問,建議收藏
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/319702.html
標籤:java
