一文講解MySQL的主從復(fù)制
阿粉在前面的幾篇文章中,說了索引的分析,索引的原理,以及慢查詢應(yīng)該怎么去做合理的優(yōu)化,接下來阿粉也給大家說說這個 MySQL 的組從復(fù)制到底是個怎么回事。
主從模式
MySQL主從模式是指數(shù)據(jù)可以從一個MySQL數(shù)據(jù)庫服務(wù)器主節(jié)點復(fù)制到一個或多個從節(jié)點。MySQL 默 認(rèn)采用異步復(fù)制方式,這樣從節(jié)點不用一直訪問主服務(wù)器來更新自己的數(shù)據(jù),從節(jié)點可以復(fù)制主數(shù)據(jù)庫 中的所有數(shù)據(jù)庫,或者特定的數(shù)據(jù)庫,或者特定的表。
mysql主從復(fù)制用途:
- 實時災(zāi)備,用于故障切換(高可用)
- 讀寫分離,提供查詢服務(wù)(讀擴展)
- 數(shù)據(jù)備份,避免影響業(yè)務(wù)(高可用)
主從部署必要條件:
- 從庫服務(wù)器能連通主庫
- 主庫開啟binlog日志(設(shè)置log-bin參數(shù))
- 主從server-id不
上面這些就是我們?nèi)绻胍渴鹨惶讓儆谧约旱?MySQL 的主從復(fù)制時,需要的條件,那么主從復(fù)制都是什么原理呢?
主從復(fù)制的步驟
主從復(fù)制整體分為以下三個步驟:
第一步:主庫將數(shù)據(jù)庫的變更操作記錄到Binlog日志文件中
第二步:從庫讀取主庫中的Binlog日志文件信息寫入到從庫的Relay Log中繼日志中
第三步:從庫讀取中繼日志信息在從庫中進行Replay,更新從庫數(shù)據(jù)信息
上面的是文字描述,
我們再來一張原理圖看看:
在上述三個過程中,涉及了Master的BinlogDump Thread和Slave的I/O Thread、SQL Thread,它們的作用如下:
- Master服務(wù)器對數(shù)據(jù)庫更改操作記錄在Binlog中,BinlogDump Thread接到寫入請求后,讀取 Binlog信息推送給Slave的I/O Thread。
- Slave的I/O Thread將讀取到的Binlog信息寫入到本地Relay Log中。
- Slave的SQL Thread檢測到Relay Log的變更請求,解析relay log中內(nèi)容在從庫上執(zhí)行。 上述過程都是異步操作,俗稱異步復(fù)制,存在數(shù)據(jù)延遲現(xiàn)象。
但是如果我們這么看主從復(fù)制的話,是不是會發(fā)現(xiàn)一些問題呢?
MySQL主從復(fù)制的問題:
- 主庫宕機后,數(shù)據(jù)可能丟失
- 從庫只有一個SQL Thread,主庫寫壓力大,復(fù)制很可能延時
一般的,如果我們做了主從復(fù)制的話,那么數(shù)據(jù)庫一定出現(xiàn)過復(fù)制延遲的情況,如果你沒遇到過,說明你沒有發(fā)現(xiàn)過,但是實際上是肯定有過的,除非你已經(jīng)想到了如何去解決這個問題了,那么解決這個問題的方式是什么呢?
- 半同步復(fù)制---解決數(shù)據(jù)丟失的問題
- 并行復(fù)制----解決從庫復(fù)制延遲的問題
那么什么是半同步復(fù)制,什么是并行復(fù)制呢?
半同步復(fù)制
為了提升數(shù)據(jù)安全,MySQL讓Master在某一個時間點等待Slave節(jié)點的 ACK(Acknowledge character)消息,接收到ACK消息后才進行事務(wù)提交,這也是半同步復(fù)制的基礎(chǔ)。
- 當(dāng)Master不需要關(guān)注Slave是否接受到Binlog Event時,即為傳統(tǒng)的主從復(fù)制。
- 當(dāng)Master需要在第三步等待Slave返回ACK時,即為 after-commit,半同步復(fù)制(MySQL 5.5引入)。
- 當(dāng)Master需要在第二步等待 Slave 返回 ACK 時,即為 after-sync,增強半同步(MySQL 5.7引入)。
主庫等待從庫寫入 relay log 并返回 ACK 后才進行Engine Commit。
并行復(fù)制
其實 MySQL 的并行復(fù)制,每個版本都是不一樣的,因為他們的實現(xiàn)原理是不一樣的。
MySQL從5.6版本開始追加了并行復(fù)制功能,目的就是為了改善復(fù)制延遲問題,并行復(fù)制稱為enhanced multi-threaded slave(簡稱MTS)。
在從庫中有兩個線程IO Thread和SQL Thread,都是單線程模式工作,因此有了延遲問題,我們可以采 用多線程機制來加強,減少從庫復(fù)制延遲。
MySQL5.7版本,基于組提交的并行復(fù)制,這個才是真正意義的并行復(fù)制,從庫的并行復(fù)制跟master庫的是一致,并行復(fù)制基于一個前提,即所有已經(jīng)處于prepare階段的事務(wù),都是可以并行提交的。
MySQL8.0版本,基于write-set的并行復(fù)制,MySQL會有一個集合變量用來存儲事務(wù)修改的記錄信息(主鍵哈希值),當(dāng)新的修改時已提交時,會進行判斷是否沖突,不沖突即可合并,這樣的并行的顆粒度就到row級別了,并行復(fù)制的速度更快
其實如果你想要進行并行復(fù)制的話,那么你還需要知道如何去進行并行復(fù)制的調(diào)優(yōu),只有這樣,你才能掌握好這個主從復(fù)制。
binlog_transaction_dependency_history_size 用于控制集合變量的大小。
binlog_transaction_depandency_tracking 用于控制binlog文件中事務(wù)之間的依賴關(guān)系,即last_committed值。
transaction_write_set_extraction用于控制事務(wù)的檢測算法,參數(shù)值為:OFF、 XXHASH64、MURMUR32
master_info_repository開啟MTS功能后,務(wù)必將參數(shù)master_info_repostitory設(shè)置為TABLE,這樣性能可以有50%~80%的提升。這是因為并行復(fù)制開啟后對于元master.info這個文件的更新將會大幅提升,資源的競爭也會變大。
slave_parallel_workers若將slave_parallel_workers設(shè)置為0,則MySQL 5.7退化為原單線程復(fù)制,但將 slave_parallel_workers設(shè)置為1,則SQL線程功能轉(zhuǎn)化為coordinator線程,但是只有1個worker線程進行回放,也是單線程復(fù)制。然而,這兩種性能卻又有一些的區(qū)別,因為多了一次coordinator線程的轉(zhuǎn)發(fā),因此slave_parallel_workers=1的性能反而比0還要差。
這些參數(shù)實際上都是非常要掌握的,不然你再設(shè)置并行復(fù)制的時候,會遇到各種各樣的問題,所以你學(xué)會了么?
文章參考
《MySQL海量數(shù)據(jù)優(yōu)化》
《MySQL必知必會》
《MySQL拍錯指南》