MySQL的主从复制
MySQL的主從復(fù)制
目錄
- 為什么需要主從復(fù)制?
- MySQL 主從復(fù)制概念
- MySQL 主從復(fù)制主要用途
- MySQL主從形式
- 一主一從
- 一主多從,提高系統(tǒng)的讀性能
- 多主一從 (從5.7開始支持)
- 雙主復(fù)制
- 級(jí)聯(lián)復(fù)制
- MySQL 主從復(fù)制原理
- MySQL主從復(fù)制的過程
- MySQL 主從復(fù)制模式
- 異步模式(mysql async-mode)
- 半同步模式(mysql semi-sync)
- 全同步模式
- MySQL的復(fù)制機(jī)制
- binlog記錄模式
- GTID復(fù)制模式
- mysql主從同步延時(shí)分析
- 多線程復(fù)制MTS
回到頂部
為什么需要主從復(fù)制?
回到頂部
MySQL 主從復(fù)制概念
MySQL 主從復(fù)制是指數(shù)據(jù)可以從一個(gè)MySQL數(shù)據(jù)庫服務(wù)器主節(jié)點(diǎn)復(fù)制到一個(gè)或多個(gè)從節(jié)點(diǎn)。MySQL 默認(rèn)采用異步復(fù)制方式,這樣從節(jié)點(diǎn)不用一直訪問主服務(wù)器來更新自己的數(shù)據(jù),數(shù)據(jù)的更新可以在遠(yuǎn)程連接上進(jìn)行,從節(jié)點(diǎn)可以復(fù)制主數(shù)據(jù)庫中的所有數(shù)據(jù)庫或者特定的數(shù)據(jù)庫,或者特定的表。
回到頂部
MySQL 主從復(fù)制主要用途
-
讀寫分離
在開發(fā)工作中,有時(shí)候會(huì)遇見某個(gè)sql 語句需要鎖表,導(dǎo)致暫時(shí)不能使用讀的服務(wù),這樣就會(huì)影響現(xiàn)有業(yè)務(wù),使用主從復(fù)制,讓主庫負(fù)責(zé)寫,從庫負(fù)責(zé)讀,這樣,即使主庫出現(xiàn)了鎖表的情景,通過讀從庫也可以保證業(yè)務(wù)的正常運(yùn)作。
-
數(shù)據(jù)實(shí)時(shí)備份,當(dāng)系統(tǒng)中某個(gè)節(jié)點(diǎn)出現(xiàn)故障的時(shí)候,方便切換
-
高可用HA
-
架構(gòu)擴(kuò)展
隨著系統(tǒng)中業(yè)務(wù)訪問量的增大,如果是單機(jī)部署數(shù)據(jù)庫,就會(huì)導(dǎo)致I/O訪問頻率過高。有了主從復(fù)制,增加多個(gè)數(shù)據(jù)存儲(chǔ)節(jié)點(diǎn),將負(fù)載分布在多個(gè)從節(jié)點(diǎn)上,降低單機(jī)磁盤I/O訪問的頻率,提高單個(gè)機(jī)器的I/O性能。
回到頂部
MySQL主從形式
一主一從
一主多從,提高系統(tǒng)的讀性能
一主一從和一主多從是最常見的主從架構(gòu),實(shí)施起來簡單并且有效,不僅可以實(shí)現(xiàn)HA,而且還能讀寫分離,進(jìn)而提升集群的并發(fā)能力。
多主一從 (從5.7開始支持)
多主一從可以將多個(gè)mysql數(shù)據(jù)庫備份到一臺(tái)存儲(chǔ)性能比較好的服務(wù)器上。
雙主復(fù)制
雙主復(fù)制,也就是互做主從復(fù)制,每個(gè)master既是master,又是另外一臺(tái)服務(wù)器的slave。這樣任何一方所做的變更,都會(huì)通過復(fù)制應(yīng)用到另外一方的數(shù)據(jù)庫中。
級(jí)聯(lián)復(fù)制
級(jí)聯(lián)復(fù)制模式下,部分slave的數(shù)據(jù)同步不連接主節(jié)點(diǎn),而是連接從節(jié)點(diǎn)。因?yàn)槿绻鞴?jié)點(diǎn)有太多的從節(jié)點(diǎn),就會(huì)損耗一部分性能用于replication,那么我們可以讓3~5個(gè)從節(jié)點(diǎn)連接主節(jié)點(diǎn),其它從節(jié)點(diǎn)作為二級(jí)或者三級(jí)與從節(jié)點(diǎn)連接,這樣不僅可以緩解主節(jié)點(diǎn)的壓力,并且對(duì)數(shù)據(jù)一致性沒有負(fù)面影響。
回到頂部
MySQL 主從復(fù)制原理
MySQL主從復(fù)制涉及到三個(gè)線程,一個(gè)運(yùn)行在主節(jié)點(diǎn)(log dump thread),其余兩個(gè)(I/O thread, SQL thread)運(yùn)行在從節(jié)點(diǎn),如下圖所示:
- 主節(jié)點(diǎn) binary log dump 線程作用
當(dāng)從節(jié)點(diǎn)連接主節(jié)點(diǎn)時(shí),主節(jié)點(diǎn)會(huì)創(chuàng)建一個(gè)log dump 線程,用于發(fā)送bin-log的內(nèi)容。在讀取bin-log中的操作時(shí),此線程會(huì)對(duì)主節(jié)點(diǎn)上的bin-log加鎖,當(dāng)讀取完成,甚至在發(fā)動(dòng)給從節(jié)點(diǎn)之前,鎖會(huì)被釋放。
- 從節(jié)點(diǎn)I/O線程作用
當(dāng)從節(jié)點(diǎn)上執(zhí)行start slave命令之后,從節(jié)點(diǎn)會(huì)創(chuàng)建一個(gè)I/O線程用來連接主節(jié)點(diǎn),請(qǐng)求主庫中更新的bin-log。I/O線程接收到主節(jié)點(diǎn)binlog dump 進(jìn)程發(fā)來的更新之后,保存在本地relay-log中。
- 從節(jié)點(diǎn)SQL線程作用
SQL線程負(fù)責(zé)讀取relay log中的內(nèi)容,解析成具體的操作并執(zhí)行,最終保證主從數(shù)據(jù)的一致性。
對(duì)于每一個(gè)主從連接,都需要三個(gè)進(jìn)程來完成。當(dāng)主節(jié)點(diǎn)有多個(gè)從節(jié)點(diǎn)時(shí),主節(jié)點(diǎn)會(huì)為每一個(gè)當(dāng)前連接的從節(jié)點(diǎn)建一個(gè)binary log dump 進(jìn)程,而每個(gè)從節(jié)點(diǎn)都有自己的I/O進(jìn)程,SQL進(jìn)程。從節(jié)點(diǎn)用兩個(gè)線程將從主庫拉取更新和執(zhí)行分成獨(dú)立的任務(wù),這樣在執(zhí)行同步數(shù)據(jù)任務(wù)的時(shí)候,不會(huì)降低讀操作的性能。比如,如果從節(jié)點(diǎn)沒有運(yùn)行,此時(shí)I/O進(jìn)程可以很快從主節(jié)點(diǎn)獲取更新,盡管SQL進(jìn)程還沒有執(zhí)行。如果在SQL進(jìn)程執(zhí)行之前從節(jié)點(diǎn)服務(wù)停止,至少I/O進(jìn)程已經(jīng)從主節(jié)點(diǎn)拉取到了最新的變更并且保存在本地relay日志中,當(dāng)服務(wù)再次起來之后,就可以完成數(shù)據(jù)的同步。
回到頂部
MySQL主從復(fù)制的過程
要實(shí)施復(fù)制,首先必須打開Master 端的binary log(bin-log)功能,否則無法實(shí)現(xiàn)。因?yàn)檎麄€(gè)復(fù)制過程實(shí)際上就是Slave 從Master 端獲取該日志然后再在自己身上完全順序的執(zhí)行日志中所記錄的各種操作
回到頂部
MySQL 主從復(fù)制模式
MySQL 主從復(fù)制默認(rèn)是異步的模式。MySQL增刪改操作會(huì)全部記錄在binary log中,當(dāng)slave節(jié)點(diǎn)連接master時(shí),會(huì)主動(dòng)從master處獲取最新的bin log文件。并把bin log中的sql relay。
異步模式(mysql async-mode)
異步模式如下圖所示,這種模式下,主節(jié)點(diǎn)不會(huì)主動(dòng)push bin log到從節(jié)點(diǎn),這樣有可能導(dǎo)致failover的情況下,也許從節(jié)點(diǎn)沒有即時(shí)地將最新的bin log同步到本地。
半同步模式(mysql semi-sync)
這種模式下主節(jié)點(diǎn)只需要接收到其中一臺(tái)從節(jié)點(diǎn)的返回信息,就會(huì)commit;否則需要等待直到超時(shí)時(shí)間然后切換成異步模式再提交;這樣做的目的可以使主從數(shù)據(jù)庫的數(shù)據(jù)延遲縮小,可以提高數(shù)據(jù)安全性,確保了事務(wù)提交后,binlog至少傳輸?shù)搅艘粋€(gè)從節(jié)點(diǎn)上,不能保證從節(jié)點(diǎn)將此事務(wù)更新到db中。性能上會(huì)有一定的降低,響應(yīng)時(shí)間會(huì)變長。如下圖所示:
全同步模式
全同步模式是指主節(jié)點(diǎn)和從節(jié)點(diǎn)全部執(zhí)行了commit并確認(rèn)才會(huì)向客戶端返回成功。
回到頂部
MySQL的復(fù)制機(jī)制
binlog記錄模式
MySQL 主從復(fù)制有三種方式:基于SQL語句的復(fù)制(statement-based replication,SBR),基于行的復(fù)制(row-based replication,RBR),混合模式復(fù)制(mixed-based replication,MBR)。對(duì)應(yīng)的binlog文件的格式也有三種:STATEMENT,ROW,MIXED。
GTID復(fù)制模式
在MySQL 5.6里面,不用再找binlog和pos點(diǎn),我們只需要知道主節(jié)點(diǎn)的ip,端口,以及賬號(hào)密碼就行,因?yàn)閺?fù)制是自動(dòng)的,MySQL會(huì)通過內(nèi)部機(jī)制GTID自動(dòng)找點(diǎn)同步。
基于GTID復(fù)制實(shí)現(xiàn)的工作原理
回到頂部
mysql主從同步延時(shí)分析
mysql的主從復(fù)制都是單線程的操作,主庫對(duì)所有DDL和DML產(chǎn)生的日志寫進(jìn)binlog,由于binlog是順序?qū)?#xff0c;所以效率很高,slave的sql thread線程將主庫的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是隨機(jī)的,不是順序,所以成本要高很多,另一方面,由于sql thread也是單線程的,當(dāng)主庫的并發(fā)較高時(shí),產(chǎn)生的DML數(shù)量超過slave的SQL thread所能處理的速度,或者當(dāng)slave中有大型query語句產(chǎn)生了鎖等待,那么延時(shí)就產(chǎn)生了。
解決方案:
mysql5.7之后使用MTS并行復(fù)制技術(shù)
多線程復(fù)制MTS
在MYSQL5.6版本中,多線程復(fù)制基于schema來實(shí)現(xiàn),將多個(gè)數(shù)據(jù)庫下的事務(wù)按照數(shù)據(jù)庫拆分到多個(gè)線程上執(zhí)行,保證數(shù)據(jù)庫級(jí)別的事務(wù)一致性。
在MYSQL5.7版本后,多線程復(fù)制基于主庫上并發(fā)信息來實(shí)現(xiàn),主庫上并發(fā)提交的事務(wù)不存在事務(wù)沖突,在從庫上拆分到多個(gè)線程執(zhí)行,保證實(shí)例級(jí)別的事務(wù)一致性。
MySQL5.6 基于schema的并行復(fù)制
slave-parallel-type=DATABASE(不同庫的事務(wù),沒有鎖沖突),并行復(fù)制的目的就是要讓slave盡可能的多線程跑起來,當(dāng)然基于庫級(jí)別的多線程也是一種方式(不同庫的事務(wù),沒有鎖沖突)。
**優(yōu)點(diǎn):**實(shí)現(xiàn)相對(duì)來說簡單,對(duì)用戶來說使用起來也簡單
缺點(diǎn): 由于是基于庫的,那么并行的粒度非常粗,現(xiàn)在很多公司的架構(gòu)是一庫一實(shí)例,針對(duì)這樣的架構(gòu),5.6的并行復(fù)制無能為力。當(dāng)然還有就是主從事務(wù)的先后順序,對(duì)于5.6也是個(gè)大問題
MySQL 5.6版本開啟并行復(fù)制功能,那么SQL線程就變?yōu)榱薱oordinator線程,coordinator線程主要負(fù)責(zé)以前兩部分的內(nèi)容:
- 若判斷可以并行執(zhí)行,那么選擇worker線程執(zhí)行事務(wù)的二進(jìn)制日志
- 若判斷不可以并行執(zhí)行,如該操作是DDL,亦或者是事務(wù)跨schema操作,則等待所有的worker線程執(zhí)行完成之后,再執(zhí)行當(dāng)前的日志
這意味著coordinator線程并不是僅將日志發(fā)送給worker線程,自己也可以回放日志,但是所有可以并行的操作交付由worker線程完成。coordinator線程與worker是典型的生產(chǎn)者與消費(fèi)者模型。
上述機(jī)制實(shí)現(xiàn)了基于schema的并行復(fù)制存在兩個(gè)問題,首先是crash safe功能不好做,因?yàn)榭赡苤髨?zhí)行的事務(wù)由于并行復(fù)制的關(guān)系先完成執(zhí)行,那么當(dāng)發(fā)生crash的時(shí)候,這部分的處理邏輯是比較復(fù)雜的。從代碼上看,5.6這里引入了Low-Water-Mark標(biāo)記來解決該問題,從設(shè)計(jì)上看(WL#5569),其是希望借助于日志的冪等性來解決該問題,不過5.6的二進(jìn)制日志回放還不能實(shí)現(xiàn)冪等性。另一個(gè)最為關(guān)鍵的問題是這樣設(shè)計(jì)的并行復(fù)制效果并不高,如果用戶實(shí)例僅有一個(gè)庫,那么就無法實(shí)現(xiàn)并行回放,甚至性能會(huì)比原來的單線程更差。而單庫多表是比多庫多表更為常見的一種情形。
MySQL 5.7基于組提交的并行復(fù)制
MySQL 5.7才可稱為真正的并行復(fù)制,這其中最為主要的原因就是slave服務(wù)器的回放與主機(jī)是一致的即master服務(wù)器上是怎么并行執(zhí)行的slave上就怎樣進(jìn)行并行回放。不再有庫的并行復(fù)制限制,對(duì)于二進(jìn)制日志格式也無特殊的要求(基于庫的并行復(fù)制也沒有要求)。從MySQL官方來看,其并行復(fù)制的原本計(jì)劃是支持表級(jí)的并行復(fù)制和行級(jí)的并行復(fù)制,行級(jí)的并行復(fù)制通過解析ROW格式的二進(jìn)制日志的方式來完成,WL#4648。但是最終出現(xiàn)給小伙伴的確是在開發(fā)計(jì)劃中稱為:MTS: Prepared transactions slave parallel applier,可見:WL#6314。該并行復(fù)制的思想最早是由MariaDB的Kristain提出,并已在MariaDB 10中出現(xiàn),相信很多選擇MariaDB的小伙伴最為看重的功能之一就是并行復(fù)制。
MySQL 5.7并行復(fù)制的思想簡單易懂,一言以蔽之:一個(gè)組提交的事務(wù)都是可以并行回放,因?yàn)檫@些事務(wù)都已進(jìn)入到事務(wù)的prepare階段,則說明事務(wù)之間沒有任何沖突(否則就不可能提交)。
為了兼容MySQL 5.6基于庫的并行復(fù)制,5.7引入了新的變量slave-parallel-type,其可以配置的值有:
- DATABASE:默認(rèn)值,基于庫的并行復(fù)制方式
- LOGICAL_CLOCK:基于組提交的并行復(fù)制方式
支持并行復(fù)制的GTID(5.7之后支持)
在MySQL 5.7版本中,其設(shè)計(jì)方式是將組提交的信息存放在GTID中。那么如果用戶沒有開啟GTID功能,即將參數(shù)gtid_mode設(shè)置為OFF,MySQL 5.7又引入了稱之為Anonymous_Gtid的二進(jìn)制日志event類型,意味著在MySQL 5.7版本中即使不開啟GTID,每個(gè)事務(wù)開始前也是會(huì)存在一個(gè)Anonymous_Gtid,而這GTID中就存在著組提交的信息。
然而,通過上述的SHOW BINLOG EVENTS,我們并沒有發(fā)現(xiàn)有關(guān)組提交的任何信息。但是通過mysqlbinlog工具,用戶就能發(fā)現(xiàn)組提交的內(nèi)部信息:
可以發(fā)現(xiàn)較之原來的二進(jìn)制日志內(nèi)容多了last_committed和sequence_number,last_committed表示事務(wù)提交的時(shí)候,上次事務(wù)提交的編號(hào),如果事務(wù)具有相同的last_committed,表示這些事務(wù)都在一組內(nèi),可以進(jìn)行并行的回放。例如上述last_committed為0的事務(wù)有6個(gè),表示組提交時(shí)提交了6個(gè)事務(wù),而這6個(gè)事務(wù)在從機(jī)是可以進(jìn)行并行回放的。
總結(jié)
以上是生活随笔為你收集整理的MySQL的主从复制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Crystal Reports 2008
- 下一篇: MySql学习【一】mysql的安装,操