欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

MySQL中主從復(fù)制的原理是什么

MySQL中主從復(fù)制的原理是什么,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)網(wǎng)站空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、大關(guān)網(wǎng)站維護(hù)、網(wǎng)站推廣。

0. 主從復(fù)制

首先主從復(fù)制是什么?簡(jiǎn)單來(lái)說(shuō)是讓一臺(tái)MySQL服務(wù)器去復(fù)制另一臺(tái)MySQL的數(shù)據(jù),使兩個(gè)服務(wù)器的數(shù)據(jù)保持一致。

這種方式與redis的主從復(fù)制的思路沒(méi)有太大的出入。如果你對(duì)Redis的主從復(fù)制感興趣可以去看看《Redis的主從復(fù)制》。那既然Redis和MySQL都采用了復(fù)制這種方式,主從復(fù)制所帶來(lái)的意義是什么呢?

通過(guò)復(fù)制功能,構(gòu)建一個(gè)或者多個(gè)從庫(kù),可以提高數(shù)據(jù)庫(kù)的高可用性、可擴(kuò)展性,同時(shí)實(shí)現(xiàn)負(fù)載均衡。當(dāng)主庫(kù)發(fā)生故障時(shí),可以快速的切到其某一個(gè)從庫(kù),并將該從庫(kù)提升為主庫(kù),因?yàn)閿?shù)據(jù)都一樣,所以不會(huì)影響系統(tǒng)的運(yùn)行;當(dāng)MySQL服務(wù)器需要扛住更多的讀請(qǐng)求時(shí),可以把讀請(qǐng)求的流量分流到各個(gè)從庫(kù)上去,寫(xiě)請(qǐng)求則轉(zhuǎn)發(fā)給主庫(kù),形成讀寫(xiě)分離的架構(gòu),來(lái)提供更好的讀擴(kuò)展和請(qǐng)求的負(fù)載均衡。

讀寫(xiě)分離的架構(gòu)應(yīng)用的其實(shí)非常廣泛,就比如MySQL,還有Redis,以及我們熟悉的Zookeeper,Zookeeper的Follower收到讀請(qǐng)求不會(huì)自己處理,而是會(huì)將讀請(qǐng)求轉(zhuǎn)發(fā)給Leader,感興趣的可以自己下來(lái)了解一下,這里就不偏題了。

1. 復(fù)制原理

MySQL的主從復(fù)制支持兩種方式:

  • 基于行

  • 基于語(yǔ)句

基于語(yǔ)句的復(fù)制在MySQL3.23中就已經(jīng)有了,而基于語(yǔ)句的方式則在5.1中才實(shí)現(xiàn)。其本質(zhì)都是基于主庫(kù)的binlog來(lái)實(shí)現(xiàn)的,主庫(kù)記錄binlog,然后從庫(kù)將binlog在自己的服務(wù)器上重放,從而保證了主、從的數(shù)據(jù)一致性。

1.1 binlog

MySQL中日志分為兩個(gè)維度,一個(gè)是MySQL服務(wù)器的,一個(gè)是底層存儲(chǔ)引擎的。而上文提到的binlog就是屬于MySQL服務(wù)器的日志,binlog也叫二進(jìn)制日志,記錄了所有對(duì)MySQL所做的更改。

基于行、語(yǔ)句的復(fù)制方式跟binlog的存儲(chǔ)方式有關(guān)系。binlog有三種存儲(chǔ)格式,分別是Statement、Row和Mixed。

  • Statement 基于語(yǔ)句,只記錄對(duì)數(shù)據(jù)做了修改的SQL語(yǔ)句,能夠有效的減少binlog的數(shù)據(jù)量,提高讀取、基于binlog重放的性能

  • Row  只記錄被修改的行,所以Row記錄的binlog日志量一般來(lái)說(shuō)會(huì)比Statement格式要多。基于Row的binlog日志非常完整、清晰,記錄了所有數(shù)據(jù)的變動(dòng),但是缺點(diǎn)是可能會(huì)非常多,例如一條update語(yǔ)句,有可能是所有的數(shù)據(jù)都有修改;再例如alter  table之類(lèi)的,修改了某個(gè)字段,同樣的每條記錄都有改動(dòng)。

  • Mixed Statement和Row的結(jié)合,怎么個(gè)結(jié)合法呢。例如像update或者alter  table之類(lèi)的語(yǔ)句修改,采用Statement格式。其余的對(duì)數(shù)據(jù)的修改例如update和delete采用Row格式進(jìn)行記錄。

為什么會(huì)有這么多方式呢?因?yàn)镾tatement只會(huì)記錄SQL語(yǔ)句,但是并不能保證所有情況下這些語(yǔ)句在從庫(kù)上能夠正確的被重放出來(lái)。因?yàn)榭赡茼樞虿粚?duì)。

MySQL什么時(shí)候會(huì)記錄binlog呢?是在事務(wù)提交的時(shí)候,并不是按照語(yǔ)句的執(zhí)行順序來(lái)記錄,當(dāng)記錄完binlog之后,就會(huì)通知底層的存儲(chǔ)引擎提交事務(wù),所以有可能因?yàn)檎Z(yǔ)句順序錯(cuò)誤導(dǎo)致語(yǔ)句出錯(cuò)。

1.2 查看binlog

這里拿MySQL 5.6舉例子,binlog默認(rèn)是處于關(guān)閉狀態(tài)的。我們可以通過(guò)命令show variables like '%log_bin%'  來(lái)查看關(guān)于binlog的配置。

MySQL中主從復(fù)制的原理是什么

默認(rèn)配置

log_bin代表是否開(kāi)啟了binlog,其默認(rèn)值為OFF。

  • log_bin 代表是否開(kāi)啟了binlog,其默認(rèn)值為OFF

  • log_bin_basename binlog存儲(chǔ)文件的完整名稱(chēng),會(huì)在默認(rèn)的文件名后面添加上遞增的序號(hào),就例如mysql-bin.000001

  • log_bin_index binlog索引文件名稱(chēng),例如mysql-bin.index

  • sql_log_bin 在binlog開(kāi)啟的時(shí)候,可以禁用當(dāng)前session的binlog

你可以在MySQL中通過(guò)命令show binary logs查看所有的binlog文件

圖片

查看binlog

知道了有哪些文件之后我們可以來(lái)看看binlog文件中的內(nèi)容,可以在MySQL通過(guò)show binlog events命令來(lái)查看。

show binglog events  查看第一個(gè)binlog文件,我們也可以通過(guò)in參數(shù)來(lái)指定,假設(shè)我們想看的文件名是mysql-bin.000001,那么可以使用命令show binlog  events in 'mysql-bin.000001'來(lái)查看指定的binlog文件

MySQL中主從復(fù)制的原理是什么

查看binlog

接下來(lái)我們來(lái)看看我們?cè)贛ySQL中的操作所對(duì)應(yīng)的binlog內(nèi)容分別是什么。

初始化

我們上面提到過(guò),binlog是由一個(gè)一個(gè)的event組成的。從MySQL  5.0開(kāi)始,binlog的第一個(gè)event都為Format_desc,位于圖中的Event_type那一列。可以看到內(nèi)容為Server  ver;5.6.50-log, Binlog ver: 4,說(shuō)明當(dāng)前使用的MySQL版本為5.6.50,Binlog的版本是V4。

創(chuàng)建數(shù)據(jù)庫(kù)

然后我創(chuàng)建了一個(gè)名為student的DB,其Event_type是Query,這個(gè)event的內(nèi)容為CREATE DATABASE student  DEFAULT CHARACTER SET = utf8mb4,一個(gè)建庫(kù)語(yǔ)句。

新建表

然后我創(chuàng)建了一個(gè)名為student的表,Event_type也是Query,內(nèi)容為use student; CREATE TABLE student  (id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT),一個(gè)建表語(yǔ)句。

插入數(shù)據(jù)

然后我們執(zhí)行INSERT語(yǔ)句給該表插入兩行數(shù)據(jù),再次查看binlog。

INSERT INTO `student` (`id`, `name`) VALUES (NULL, '張三'); INSERT INTO `student` (`id`, `name`) VALUES (NULL, '李四');

MySQL中主從復(fù)制的原理是什么

image-20210106123550397

可以看到每次INSERT都會(huì)開(kāi)啟一個(gè)事務(wù),你可能會(huì)疑惑,我們只是簡(jiǎn)單的執(zhí)行了INSERT語(yǔ)句,沒(méi)有顯示的開(kāi)啟事務(wù)。那為什么會(huì)有事務(wù)產(chǎn)生呢?

這是因?yàn)镸ySQL采用了自動(dòng)提交(AUTOCOMMIT)的機(jī)制,我使用的InnoDB存儲(chǔ)引擎,是支持事務(wù)的,所有的用戶活動(dòng)都發(fā)生在事務(wù)中。我們可以通過(guò)show  variables like '%AUTOCOMMIT%';命令查看,如果結(jié)果是ON則代表是開(kāi)啟的。

1.3 復(fù)制的核心步驟

我們假設(shè)主庫(kù)已經(jīng)開(kāi)啟了binlog,并正常的記錄binlog。

首先從庫(kù)啟動(dòng)I/O線程,跟主庫(kù)建立客戶端連接。

主庫(kù)啟動(dòng)binlog dump線程,讀取主庫(kù)上的binlog event發(fā)送給從庫(kù)的I/O線程,I/O線程獲取到binlog  event之后將其寫(xiě)入到自己的Relay Log中。

然后從庫(kù)啟動(dòng)SQL線程,將Relay中的數(shù)據(jù)進(jìn)行重放,完成從庫(kù)的數(shù)據(jù)更新。

總結(jié)來(lái)說(shuō),主庫(kù)上只會(huì)有一個(gè)線程,而從庫(kù)上則會(huì)有兩個(gè)線程。

MySQL中主從復(fù)制的原理是什么

主從復(fù)制流程

1.4 Relay Log

relay log其實(shí)和binlog沒(méi)有太大的區(qū)別,在MySQL 4.0 之前是沒(méi)有Relay  Log這部分的,整個(gè)過(guò)程中只有兩個(gè)線程。但是這樣也帶來(lái)一個(gè)問(wèn)題,那就是復(fù)制的過(guò)程需要同步的進(jìn)行,很容易被影響,而且效率不高。例如主庫(kù)必須要等待從庫(kù)讀取完了才能發(fā)送下一個(gè)binlog事件。這就有點(diǎn)類(lèi)似于一個(gè)阻塞的信道和非阻塞的信道。

MySQL中主從復(fù)制的原理是什么

阻塞信道

阻塞信道就跟你在柜臺(tái)一樣,你要遞歸柜員一個(gè)東西,但是你和柜員之間沒(méi)有可以放東西的地方,你就只能一直把文件拿著,直到柜員接手;而非阻塞信道就像你們之間有個(gè)地方可以放文件,你就直接放上去就好了,不用等柜員接手。

引入了Relay Log之后,讓原本同步的獲取事件、重放事件解耦了,兩個(gè)步驟可以異步的進(jìn)行,Relay Log充當(dāng)了緩沖區(qū)的作用。Relay  Log有一個(gè)relay-log.info的文件,用于記錄當(dāng)前復(fù)制的進(jìn)度,下一個(gè)事件從什么Pos開(kāi)始寫(xiě)入,該文件由SQL線程負(fù)責(zé)更新。

1.5 Relay Log核心參數(shù)

接下來(lái)讓我們了解一下Relay Log的核心參數(shù)。

  • max_relay_log_size 中繼日志的最大size,默認(rèn)值0,如果為0就會(huì)取默認(rèn)的size 1G,否則就為設(shè)置的值

  • relay_log 定義relay的名稱(chēng),默認(rèn)為主機(jī)名+relay-bin,例如像hostname-relay-bin

  • relay_log_basename 中繼日志的全路徑,即路徑 +  文件名,例如/path/to/hostname-relay-bin,最大長(zhǎng)度為256

  • relay_log_index 定義中繼日志的索引文件的全路徑,同樣其最大的長(zhǎng)度為256. 其默認(rèn)值為hostname +  relay-bin.index,例如/path/to/hostname-relay-bin.index

  • relay_log_info_file 定義relay-log.info文件的名稱(chēng)

  • relay_log_info_repository 存放relay  log重放的數(shù)據(jù)的方式,可以設(shè)置為FILE和TABLE。FILE代表將中繼日志重放的數(shù)據(jù)記錄在relay-info.log中,TABLE則將其存放在slave_relay_log_info這張表里。

  • relay_log_purge 是否自動(dòng)清空不需要的中繼日志,默認(rèn)值為ON

  • relay_log_recovery 當(dāng)從庫(kù)宕機(jī)后,如果relay  log損壞了導(dǎo)致部分的中繼日志沒(méi)有進(jìn)行同步,則自動(dòng)放棄所有未進(jìn)行重放的中繼日志,并從主庫(kù)重新獲取,默認(rèn)值為OFF

  • relay_log_space_limit  設(shè)置中繼日志的最大值,防止寫(xiě)滿磁盤(pán)。但是不建議設(shè)置這個(gè)值,建議還是給中繼日志需要的空間,0就是不限制,0也是默認(rèn)值

  • sync_relay_log  用于控制中繼日志寫(xiě)入磁盤(pán)的變量,假設(shè)值為n,那么在中繼日志每接受n次binlog事件之后就會(huì)調(diào)用fdatasync()函數(shù)將中繼日志強(qiáng)制的刷入磁盤(pán);相反,如果值為0,則寫(xiě)入OS的緩沖區(qū)內(nèi),由OS調(diào)度決定何時(shí)將中繼日志刷入磁盤(pán),這樣一來(lái)如果在沒(méi)有刷入之前報(bào)錯(cuò)了,那么中繼日志就會(huì)丟失。默認(rèn)值是10000,也就是每向中繼日志中寫(xiě)入1w次binlog事件就將中繼日志強(qiáng)制的刷入磁盤(pán)。

  • sync_relay_log_info  該參數(shù)的影響跟參數(shù)relay_log_info_repository有一定關(guān)系,同時(shí)也跟是否使用支持事務(wù)的存儲(chǔ)引擎有關(guān)系。該值默認(rèn)也是10000.

    • relay_log_info_repository為FILE,假設(shè)設(shè)置的值為N,那么每N次事務(wù)都會(huì)都會(huì)調(diào)用fdatasync()強(qiáng)制將relay-log.info刷入磁盤(pán)

    • relay_log_info_repository為T(mén)ABLE,如果使用了支持事務(wù)的引擎,則該表每次事務(wù)結(jié)束都會(huì)被更新;如果沒(méi)有使用事務(wù)引擎則會(huì)在寫(xiě)入N個(gè)binlog事件的時(shí)候更新該表。

    • relay_log_info_repository為FILE,MySQL不會(huì)調(diào)用fdatasync(),而是將刷入磁盤(pán)的調(diào)度交給OS;

    • relay_log_info_repository為T(mén)ABLE,如果使用了支持事務(wù)的存儲(chǔ)引擎,則每次事務(wù)的時(shí)候該表都會(huì)被更新;如果沒(méi)有使用事務(wù)引擎,則永遠(yuǎn)不會(huì)被更新

    • 當(dāng)sync_relay_log_info為0時(shí)

    • 當(dāng)sync_relay_log_info大于0時(shí)

2. 復(fù)制模型

平常的開(kāi)發(fā)中,其實(shí)很少說(shuō)一上來(lái)就直接搞主從架構(gòu)的。費(fèi)時(shí)間、費(fèi)錢(qián)還引入了額外的復(fù)雜度,最后發(fā)現(xiàn)投入了這么多一個(gè)單MySQL服務(wù)器就完全能handle。

這就跟一個(gè)產(chǎn)品的架構(gòu)迭代是一樣的,剛剛起步的時(shí)候一個(gè)單體應(yīng)用足夠了。當(dāng)你的業(yè)務(wù)擴(kuò)展,請(qǐng)求膨脹,單體無(wú)法抗住壓力了,就會(huì)考慮開(kāi)始部署多實(shí)例,開(kāi)始采用微服務(wù)架構(gòu)去做橫向擴(kuò)展、負(fù)載均衡。

2.1 一主多從

當(dāng)然你也可以把它當(dāng)成一主一從。

這是最簡(jiǎn)單的模型,特別適合少量寫(xiě)、大量讀的情況。讀請(qǐng)求被分到了各個(gè)從庫(kù)上,有效的幫主庫(kù)分散了壓力,能夠提升讀并發(fā)。當(dāng)然,你也可以只是把從庫(kù)當(dāng)成一個(gè)災(zāi)備庫(kù),除了主從復(fù)制之外,沒(méi)有其他任何的請(qǐng)求和數(shù)據(jù)傳輸。

甚至你可以把其中一個(gè)備庫(kù)作為你的預(yù)發(fā)環(huán)境的數(shù)據(jù)庫(kù),當(dāng)然,這說(shuō)到底還是直接動(dòng)了生產(chǎn)環(huán)境的數(shù)據(jù)庫(kù),是一種過(guò)于理想的用途,因?yàn)檫@還涉及到生產(chǎn)環(huán)境數(shù)據(jù)庫(kù)的數(shù)據(jù)敏感性。不是所有人都能夠接觸到的,需要有完善的權(quán)限機(jī)制。

MySQL中主從復(fù)制的原理是什么

MySQL一主多從

值得注意的是,如果有n個(gè)從庫(kù),那么主庫(kù)上就會(huì)有n個(gè)binlog  dump線程。如果這個(gè)n比較大的話在復(fù)制的時(shí)候可能會(huì)造成主庫(kù)的性能抖動(dòng)。所以在從庫(kù)較多的情況下可以采用級(jí)聯(lián)復(fù)制。

2.2 級(jí)聯(lián)復(fù)制

級(jí)聯(lián)復(fù)制用大白話說(shuō)就是套娃。

本來(lái)從庫(kù)B、C、D、E、F、G都是復(fù)制的主庫(kù)A,但是現(xiàn)在由于A的壓力比較大,就不這么干了,調(diào)整成了如下的模式。

B、C復(fù)制A

D、E復(fù)制B

F、G復(fù)制C

MySQL中主從復(fù)制的原理是什么

MySQL級(jí)聯(lián)復(fù)制

這就叫級(jí)聯(lián)復(fù)制,開(kāi)啟瘋狂套娃模式。你甚至?xí)X(jué)得這種套娃很眼熟,在Redis主從復(fù)制中也可以采用級(jí)聯(lián)模式, slave去復(fù)制另一個(gè)slave。

級(jí)聯(lián)復(fù)制的好處在于很大程度上減輕了主庫(kù)的壓力,主庫(kù)只需要關(guān)心與其有直接復(fù)制關(guān)系的從庫(kù),剩下的復(fù)制則交給從庫(kù)即可。相反,由于是這種層層嵌套的關(guān)系,如果在較上層出現(xiàn)了錯(cuò)誤,會(huì)影響到掛在該服務(wù)器下的所有子庫(kù),這些錯(cuò)誤的影響效果被放大了。

2.3 主主復(fù)制

顧名思義,就是兩個(gè)主庫(kù)相互復(fù)制,客戶端可以對(duì)任意一臺(tái)主庫(kù)進(jìn)行寫(xiě)操作。任何一臺(tái)主庫(kù)服務(wù)器上的數(shù)據(jù)發(fā)生了變化都會(huì)同步到另一臺(tái)服務(wù)器上去。有點(diǎn)類(lèi)似于Eureka  Server的雙節(jié)點(diǎn)模式,兩個(gè)注冊(cè)中心相互注冊(cè)。這樣一來(lái),任何一臺(tái)掛了都不會(huì)對(duì)系統(tǒng)產(chǎn)生影響。

而且主主復(fù)制可以打破數(shù)據(jù)庫(kù)性能瓶頸,一個(gè)很酷的功能——橫向擴(kuò)展。為什么說(shuō)很酷呢,如果DB能做到橫向擴(kuò)展,那很多被數(shù)據(jù)庫(kù)并發(fā)所限制的瓶頸都可以被突破,然而...

但是主主復(fù)制其實(shí)并不可靠,兩邊的數(shù)據(jù)沖突的可能性很大。例如復(fù)制停止了,系統(tǒng)仍然在向兩個(gè)主庫(kù)中寫(xiě)入數(shù)據(jù),也就是說(shuō)一部分?jǐn)?shù)據(jù)在A,另一部分的數(shù)據(jù)在B,但是沒(méi)有相互復(fù)制,且數(shù)據(jù)也不同步了。要修復(fù)這部分?jǐn)?shù)據(jù)的難度就會(huì)變得相當(dāng)大。

所以我認(rèn)為雙主的更多的意義在于HA,而不是負(fù)載均衡。

2.4 主、被動(dòng)的主主復(fù)制

同樣還是雙主的結(jié)構(gòu),但是區(qū)別在于其中一臺(tái)是只讀的被動(dòng)服務(wù)器,客戶端不會(huì)向該庫(kù)進(jìn)行寫(xiě)操作。

其用途在哪里呢?例如我們要在不中斷服務(wù)的前提下對(duì)MySQL進(jìn)行維護(hù)、優(yōu)化,舉個(gè)例子——修改表結(jié)構(gòu)。假設(shè)我們有兩個(gè)數(shù)據(jù)庫(kù),主庫(kù)A和被動(dòng)主庫(kù)B,注意此處的被動(dòng)主庫(kù)是只讀的,我們先停止A對(duì)B的復(fù)制,也就是停掉A上的SQL線程。

MySQL中主從復(fù)制的原理是什么

主主停止復(fù)制

這樣一來(lái),我們之后在B上執(zhí)行的非常耗時(shí)、可能需要鎖表的操作就不會(huì)立即同步到A上來(lái)。因?yàn)榇藭r(shí)A正在對(duì)外提供服務(wù),所以不能使其收到影響,但是由于采用的是異步的復(fù)制模式,所以Relay  Log還是繼續(xù)由I/O線程寫(xiě)入,只是不去進(jìn)行重放。

然后我們?cè)贐上執(zhí)行此次的維護(hù)操作,注意,此時(shí)A上面發(fā)生的更新還是會(huì)正常的同步到B來(lái)。執(zhí)行完后交換讀寫(xiě)的角色。也就是讓A變成只讀的被動(dòng)主庫(kù),而B(niǎo)變?yōu)橹鲃?dòng)主庫(kù)對(duì)外提供服務(wù)。

MySQL中主從復(fù)制的原理是什么

重新開(kāi)啟SQL線程

然后重新開(kāi)啟SQL線程,A開(kāi)始去對(duì)之前Relay  Log中積累的event進(jìn)行重放。雖然A此時(shí)可能會(huì)阻塞住,但是A已經(jīng)沒(méi)有對(duì)外提供服務(wù)了,所以沒(méi)有問(wèn)題。

主、被動(dòng)下的主主模式的好處大家也就清楚了,可以在不停止服務(wù)的情況下去做數(shù)據(jù)庫(kù)的結(jié)構(gòu)更新,其次可以在主庫(kù)發(fā)生故障的情況下,快速的切換,保證數(shù)據(jù)庫(kù)的HA。

3. 復(fù)制方式

上文我們不止一次的提到了復(fù)制是異步的,接下來(lái)我們來(lái)了解一下MySQL的主從復(fù)制都有哪些方式。

3.1 異步復(fù)制

首先就是異步,這也是MySQL默認(rèn)的方式。在異步復(fù)制下,主庫(kù)不會(huì)主動(dòng)的向從庫(kù)發(fā)送消息,而是等待從庫(kù)的I/O線程建立連接,然后主庫(kù)創(chuàng)建binlog  dump線程,把binlog event發(fā)送給I/O線程,流程如下圖。

MySQL中主從復(fù)制的原理是什么

MySQL復(fù)制模式

主庫(kù)在執(zhí)行完自己的事務(wù)、記錄完binlog之后就會(huì)直接返回,不會(huì)與客戶端確認(rèn)任何結(jié)果。然后后續(xù)由binlog  dump線程異步的讀取binlog,然后發(fā)送給從庫(kù)。處理請(qǐng)求和主從復(fù)制是兩個(gè)完全異步化的過(guò)程。

3.2 同步復(fù)制

同步模式則是,主庫(kù)執(zhí)行一個(gè)事務(wù),那么主庫(kù)必須等待所有的從庫(kù)全部執(zhí)行完事務(wù)返回commit之后才能給客戶端返回成功,

MySQL中主從復(fù)制的原理是什么

同步復(fù)制

值得注意的是,主庫(kù)會(huì)直接提交事務(wù),而不是等待所有從庫(kù)返回之后再提交。MySQL只是延遲了對(duì)客戶端的返回,并沒(méi)有延后事務(wù)的提交。

同步模式用腳趾頭想知道性能會(huì)大打折扣,它把客戶端的請(qǐng)求和主從復(fù)制耦合在了一起,如果有某個(gè)從庫(kù)復(fù)制線程執(zhí)行的慢,那么對(duì)客戶端的響應(yīng)也會(huì)慢很多。

3.3 半同步復(fù)制

半同步相對(duì)于同步的區(qū)別在于,同步需要等待所有的從庫(kù)commit,而半同步只需要一個(gè)從庫(kù)commit就可以返回了。如果超過(guò)默認(rèn)的時(shí)間仍然沒(méi)有從庫(kù)commit,就會(huì)切換為異步模式再提交。客戶端也不會(huì)一直去等待了。

MySQL中主從復(fù)制的原理是什么

MySQL復(fù)制模式

因?yàn)榧词购竺嬷鲙?kù)宕機(jī)了,也能至少保證有一個(gè)從庫(kù)節(jié)點(diǎn)是可以用的,此外還減少了同步時(shí)的等待時(shí)間。

4. 復(fù)制中的數(shù)據(jù)一致性

我們?cè)?.3中討論了復(fù)制的核心步驟,看似很簡(jiǎn)單的一個(gè)流程,主庫(kù)的binlog dump去讀取binlog,然后從庫(kù)的I/O線程去讀取、寫(xiě)入Relay  Log,進(jìn)而從庫(kù)的SQL線程再讀取Relay Log進(jìn)行重放。

那如果I/O線程復(fù)制到一半自己突然掛掉了呢?又或者復(fù)制到一半主庫(kù)宕機(jī)了呢?如果和保證數(shù)據(jù)一致性的呢?

我們上面提到過(guò),有一個(gè)relay-log.info的文件,用于記錄當(dāng)前從庫(kù)正在復(fù)制的binlog和寫(xiě)入的Relay  Log的Pos,只要這個(gè)文件還在,那么當(dāng)從庫(kù)意外重啟之后,就會(huì)重新讀取文件,從上次復(fù)制的地方開(kāi)始繼續(xù)復(fù)制。這就跟Redis中的主從復(fù)制類(lèi)似,雙方要維護(hù)一個(gè)offset,通過(guò)對(duì)比offset,來(lái)進(jìn)行psync增量數(shù)據(jù)同步。

但是在MySQL  5.5以及之前,都只能將復(fù)制的進(jìn)度記錄在relog-log.info文件中。換句話說(shuō),參數(shù)relay_log_info_repository只支持FILE,可以再回到上面的1.5  Relay Log核心參數(shù)看一下。所以只有在sync_relay_log_info次事務(wù)之后才會(huì)把relay-log.info文件刷入磁盤(pán)。

如果在刷入磁盤(pán)之前從庫(kù)掛了,那么重啟之后就會(huì)發(fā)現(xiàn)SQL線程實(shí)際執(zhí)行到位置和數(shù)據(jù)庫(kù)記錄的不一致,數(shù)據(jù)一致性的問(wèn)題就這么產(chǎn)生了。

所以在MySQL  5.6時(shí),參數(shù)relay_log_info_repository支持了TABLE,這樣一來(lái)我們就可以將復(fù)制的進(jìn)度放在系統(tǒng)的mysql.slave_relay_log_info表里去,并且把更新進(jìn)度、SQL線程執(zhí)行用戶事務(wù)綁定成一個(gè)事務(wù)執(zhí)行。即使slave宕機(jī)了,我們也可以通過(guò)MySQL內(nèi)建的崩潰恢復(fù)機(jī)制來(lái)使實(shí)際執(zhí)行的位置和數(shù)據(jù)庫(kù)保存的進(jìn)度恢復(fù)到一致。

其次還有上面提到的半同步復(fù)制,主庫(kù)會(huì)先提交事務(wù),然后等待從庫(kù)的返回,再將結(jié)果返回給客戶端,但是如果在主庫(kù)等待的時(shí)候,從庫(kù)掛了呢?

此時(shí)主庫(kù)上由于事務(wù)已經(jīng)提交了,但是從庫(kù)上卻沒(méi)有這個(gè)數(shù)據(jù)。所以在MySQL  5.7時(shí)引入了無(wú)損半同步復(fù)制,增加了參數(shù)rpl_semi_sync_master_wait_point的值,在MySQL  5.7中值默認(rèn)為after_sync,在MySQL 5.6中默認(rèn)值為after_commit。

  • after_sync  主庫(kù)先不提交事務(wù),等待某一個(gè)從庫(kù)返回了結(jié)果之后,再提交事務(wù)。這樣一來(lái),如果從庫(kù)在沒(méi)有任何返回的情況下宕機(jī)了,master這邊也無(wú)法提交事務(wù)。主從仍然是一致的

  • after_commit 與之前討論的一樣,主庫(kù)先提交事務(wù),等待從庫(kù)返回結(jié)果再通知客戶端

看完上述內(nèi)容,你們掌握MySQL中主從復(fù)制的原理是什么的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

標(biāo)題名稱(chēng):MySQL中主從復(fù)制的原理是什么
本文鏈接:http://chinadenli.net/article28/gehgjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站移動(dòng)網(wǎng)站建設(shè)軟件開(kāi)發(fā)搜索引擎優(yōu)化服務(wù)器托管小程序開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管