自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入了解MySQL主從復(fù)制的原理

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

 [[375183]]

本文轉(zhuǎn)載自微信公眾號(hào)「SH的全棧筆記」,作者SH。轉(zhuǎn)載本文請(qǐng)聯(lián)系SH的全棧筆記公眾號(hào)。SH  

0. 主從復(fù)制

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

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

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

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

1. 復(fù)制原理

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

  • 基于行
  • 基于語句

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

1.1 binlog

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

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

  • Statement 基于語句,只記錄對(duì)數(shù)據(jù)做了修改的SQL語句,能夠有效的減少binlog的數(shù)據(jù)量,提高讀取、基于binlog重放的性能
  • Row 只記錄被修改的行,所以Row記錄的binlog日志量一般來說會(huì)比Statement格式要多?;赗ow的binlog日志非常完整、清晰,記錄了所有數(shù)據(jù)的變動(dòng),但是缺點(diǎn)是可能會(huì)非常多,例如一條update語句,有可能是所有的數(shù)據(jù)都有修改;再例如alter table之類的,修改了某個(gè)字段,同樣的每條記錄都有改動(dòng)。
  • Mixed Statement和Row的結(jié)合,怎么個(gè)結(jié)合法呢。例如像update或者alter table之類的語句修改,采用Statement格式。其余的對(duì)數(shù)據(jù)的修改例如update和delete采用Row格式進(jìn)行記錄。

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

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

1.2 查看binlog

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

默認(rèn)配置

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

  • log_bin 代表是否開啟了binlog,其默認(rèn)值為OFF
  • log_bin_basename binlog存儲(chǔ)文件的完整名稱,會(huì)在默認(rèn)的文件名后面添加上遞增的序號(hào),就例如mysql-bin.000001
  • log_bin_index binlog索引文件名稱,例如mysql-bin.index
  • sql_log_bin 在binlog開啟的時(shí)候,可以禁用當(dāng)前session的binlog

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

圖片

查看binlog

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

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

查看binlog

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

初始化

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

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

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

新建表

然后我創(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è)建表語句。

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

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

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

image-20210106123550397

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

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

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

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

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

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

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

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

主從復(fù)制流程

1.4 Relay Log

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

阻塞信道

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

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

1.5 Relay Log核心參數(shù)

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

  • max_relay_log_size 中繼日志的最大size,默認(rèn)值0,如果為0就會(huì)取默認(rèn)的size 1G,否則就為設(shè)置的值
  • relay_log 定義relay的名稱,默認(rèn)為主機(jī)名+relay-bin,例如像hostname-relay-bin
  • relay_log_basename 中繼日志的全路徑,即路徑 + 文件名,例如/path/to/hostname-relay-bin,最大長度為256
  • relay_log_index 定義中繼日志的索引文件的全路徑,同樣其最大的長度為256. 其默認(rèn)值為hostname + relay-bin.index,例如/path/to/hostname-relay-bin.index
  • relay_log_info_file 定義relay-log.info文件的名稱
  • 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)從庫宕機(jī)后,如果relay log損壞了導(dǎo)致部分的中繼日志沒有進(jìn)行同步,則自動(dòng)放棄所有未進(jìn)行重放的中繼日志,并從主庫重新獲取,默認(rèn)值為OFF
  • relay_log_space_limit 設(shè)置中繼日志的最大值,防止寫滿磁盤。但是不建議設(shè)置這個(gè)值,建議還是給中繼日志需要的空間,0就是不限制,0也是默認(rèn)值
  • sync_relay_log 用于控制中繼日志寫入磁盤的變量,假設(shè)值為n,那么在中繼日志每接受n次binlog事件之后就會(huì)調(diào)用fdatasync()函數(shù)將中繼日志強(qiáng)制的刷入磁盤;相反,如果值為0,則寫入OS的緩沖區(qū)內(nèi),由OS調(diào)度決定何時(shí)將中繼日志刷入磁盤,這樣一來如果在沒有刷入之前報(bào)錯(cuò)了,那么中繼日志就會(huì)丟失。默認(rèn)值是10000,也就是每向中繼日志中寫入1w次binlog事件就將中繼日志強(qiáng)制的刷入磁盤。
  • 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刷入磁盤
    • relay_log_info_repository為TABLE,如果使用了支持事務(wù)的引擎,則該表每次事務(wù)結(jié)束都會(huì)被更新;如果沒有使用事務(wù)引擎則會(huì)在寫入N個(gè)binlog事件的時(shí)候更新該表。
    • relay_log_info_repository為FILE,MySQL不會(huì)調(diào)用fdatasync(),而是將刷入磁盤的調(diào)度交給OS;
    • relay_log_info_repository為TABLE,如果使用了支持事務(wù)的存儲(chǔ)引擎,則每次事務(wù)的時(shí)候該表都會(huì)被更新;如果沒有使用事務(wù)引擎,則永遠(yuǎn)不會(huì)被更新
    • 當(dāng)sync_relay_log_info為0時(shí)
    • 當(dāng)sync_relay_log_info大于0時(shí)

2. 復(fù)制模型

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

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

2.1 一主多從

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

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

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

MySQL一主多從

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

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

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

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

B、C復(fù)制A

D、E復(fù)制B

F、G復(fù)制C

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

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

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

2.3 主主復(fù)制

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

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

但是主主復(fù)制其實(shí)并不可靠,兩邊的數(shù)據(jù)沖突的可能性很大。例如復(fù)制停止了,系統(tǒng)仍然在向兩個(gè)主庫中寫入數(shù)據(jù),也就是說一部分?jǐn)?shù)據(jù)在A,另一部分的數(shù)據(jù)在B,但是沒有相互復(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ì)向該庫進(jìn)行寫操作。

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

主主停止復(fù)制

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

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

重新開啟SQL線程

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

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

3. 復(fù)制方式

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

3.1 異步復(fù)制

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

MySQL復(fù)制模式

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

3.2 同步復(fù)制

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

同步復(fù)制

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

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

3.3 半同步復(fù)制

半同步相對(duì)于同步的區(qū)別在于,同步需要等待所有的從庫commit,而半同步只需要一個(gè)從庫commit就可以返回了。如果超過默認(rèn)的時(shí)間仍然沒有從庫commit,就會(huì)切換為異步模式再提交??蛻舳艘膊粫?huì)一直去等待了。

MySQL復(fù)制模式

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

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

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

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

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

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

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

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

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

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

  • after_sync 主庫先不提交事務(wù),等待某一個(gè)從庫返回了結(jié)果之后,再提交事務(wù)。這樣一來,如果從庫在沒有任何返回的情況下宕機(jī)了,master這邊也無法提交事務(wù)。主從仍然是一致的
  • after_commit 與之前討論的一樣,主庫先提交事務(wù),等待從庫返回結(jié)果再通知客戶端

 

責(zé)任編輯:武曉燕 來源: SH的全棧筆記
相關(guān)推薦

2024-07-04 08:00:24

2017-09-05 16:00:49

MySQL主從復(fù)制備份

2025-01-15 15:47:36

2020-04-14 16:26:22

MySQL線程同步

2021-04-28 10:13:58

zookeeperZNode核心原理

2021-01-19 12:00:39

前端監(jiān)控代碼

2024-07-04 17:22:23

2023-04-06 13:15:48

MySQL復(fù)制原理應(yīng)用實(shí)踐

2019-11-28 09:33:08

Redis架構(gòu)互聯(lián)網(wǎng)

2020-11-13 07:11:23

MySQL復(fù)制日志

2018-05-16 15:26:43

數(shù)據(jù)庫MySQL主從復(fù)制

2024-11-15 15:27:09

2025-04-07 00:00:00

MySQL數(shù)據(jù)庫服務(wù)器

2025-02-10 10:55:16

2024-03-01 18:33:59

MySQL節(jié)點(diǎn)數(shù)據(jù)

2021-06-08 07:48:27

MySQL主從配置

2018-09-04 16:20:46

MySQ索引數(shù)據(jù)結(jié)構(gòu)

2021-01-11 14:45:35

Redis數(shù)據(jù)庫命令

2023-12-25 08:02:09

2017-10-11 15:40:20

MySQL主從復(fù)制拓?fù)浣Y(jié)構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)