濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > Mysql中事務(wù)ACID的實(shí)現(xiàn)原理詳解

Mysql中事務(wù)ACID的實(shí)現(xiàn)原理詳解

熱門標(biāo)簽:電話機(jī)器人的價(jià)格多少錢一個(gè)月 中國(guó)地圖標(biāo)注公司 福建外呼電銷機(jī)器人加盟 百度地圖標(biāo)注要什么軟件 400電話申請(qǐng)廠家現(xiàn)貨 昌德訊外呼系統(tǒng) 徐涇鎮(zhèn)騰訊地圖標(biāo)注 自己做地圖標(biāo)注需要些什么 天津公司外呼系統(tǒng)軟件

引言

照例,我們先來(lái)一個(gè)場(chǎng)景~

面試官:"知道事務(wù)的四大特性么?"
你:"懂,ACID嘛,原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)!"
面試官:"你們是用mysql數(shù)據(jù)庫(kù)吧,能簡(jiǎn)單說(shuō)說(shuō)innodb中怎么實(shí)現(xiàn)這四大特性的么?“
你:"我只知道隔離性是怎么做的balabala~~"
面試官:"還是回去等通知吧~"

OK,回到正題。說(shuō)到事務(wù)的四大特性原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability),懂的人很多。但是稍微涉及細(xì)節(jié)一點(diǎn),這四大特性在數(shù)據(jù)庫(kù)中的實(shí)現(xiàn)原理是怎么樣的?那就沒(méi)有幾個(gè)人能夠答得上來(lái)了。因此,我們這篇文章著重討論一下四大特性在Mysql中的實(shí)現(xiàn)原理。

正文

我們以從A賬戶轉(zhuǎn)賬50元到B賬戶為例進(jìn)行說(shuō)明一下ACID,四大特性。

原子性

根據(jù)定義,原子性是指一個(gè)事務(wù)是一個(gè)不可分割的工作單位,其中的操作要么都做,要么都不做。即要么轉(zhuǎn)賬成功,要么轉(zhuǎn)賬失敗,是不存在中間的狀態(tài)!

如果無(wú)法保證原子性會(huì)怎么樣?

OK,就會(huì)出現(xiàn)數(shù)據(jù)不一致的情形,A賬戶減去50元,而B賬戶增加50元操作失敗。系統(tǒng)將無(wú)故丟失50元~

隔離性

根據(jù)定義,隔離性是指多個(gè)事務(wù)并發(fā)執(zhí)行的時(shí)候,事務(wù)內(nèi)部的操作與其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。

如果無(wú)法保證隔離性會(huì)怎么樣?

OK,假設(shè)A賬戶有200元,B賬戶0元。A賬戶往B賬戶轉(zhuǎn)賬兩次,金額為50元,分別在兩個(gè)事務(wù)中執(zhí)行。如果無(wú)法保證隔離性,會(huì)出現(xiàn)下面的情形


如圖所示,如果不保證隔離性,A扣款兩次,而B只加款一次,憑空消失了50元,依然出現(xiàn)了數(shù)據(jù)不一致的情形!

ps:可能有細(xì)心的讀者已經(jīng)發(fā)現(xiàn)了,mysql中是依靠鎖來(lái)解決隔離性問(wèn)題。嗯,我們后面來(lái)說(shuō)明。

持久性

根據(jù)定義,持久性是指事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)的改變就應(yīng)該是永久性的。接下來(lái)的其他操作或故障不應(yīng)該對(duì)其有任何影響。

如果無(wú)法保證持久性會(huì)怎么樣?

在Mysql中,為了解決CPU和磁盤速度不一致問(wèn)題,Mysql是將磁盤上的數(shù)據(jù)加載到內(nèi)存,對(duì)內(nèi)存進(jìn)行操作,然后再回寫磁盤。好,假設(shè)此時(shí)宕機(jī)了,在內(nèi)存中修改的數(shù)據(jù)全部丟失了,持久性就無(wú)法保證。

設(shè)想一下,系統(tǒng)提示你轉(zhuǎn)賬成功。但是你發(fā)現(xiàn)金額沒(méi)有發(fā)生任何改變,此時(shí)數(shù)據(jù)出現(xiàn)了不合法的數(shù)據(jù)狀態(tài),我們將這種狀態(tài)認(rèn)為是數(shù)據(jù)不一致的情形。

一致性

根據(jù)定義,一致性是指事務(wù)執(zhí)行前后,數(shù)據(jù)處于一種合法的狀態(tài),這種狀態(tài)是語(yǔ)義上的而不是語(yǔ)法上的。
那什么是合法的數(shù)據(jù)狀態(tài)呢?

oK,這個(gè)狀態(tài)是滿足預(yù)定的約束就叫做合法的狀態(tài),再通俗一點(diǎn),這狀態(tài)是由你自己來(lái)定義的。滿足這個(gè)狀態(tài),數(shù)據(jù)就是一致的,不滿足這個(gè)狀態(tài),數(shù)據(jù)就是不一致的!

如果無(wú)法保證一致性會(huì)怎么樣?

例一:A賬戶有200元,轉(zhuǎn)賬300元出去,此時(shí)A賬戶余額為-100元。你自然就發(fā)現(xiàn)了此時(shí)數(shù)據(jù)是不一致的,為什么呢?因?yàn)槟愣x了一個(gè)狀態(tài),余額這列必須大于0。

例二:A賬戶200元,轉(zhuǎn)賬50元給B賬戶,A賬戶的錢扣了,但是B賬戶因?yàn)楦鞣N意外,余額并沒(méi)有增加。你也知道此時(shí)數(shù)據(jù)是不一致的,為什么呢?因?yàn)槟愣x了一個(gè)狀態(tài),要求A+B的余額必須不變。

實(shí)戰(zhàn)解答

問(wèn)題一:Mysql怎么保證一致性的?

OK,這個(gè)問(wèn)題分為兩個(gè)層面來(lái)說(shuō)。

從數(shù)據(jù)庫(kù)層面,數(shù)據(jù)庫(kù)通過(guò)原子性、隔離性、持久性來(lái)保證一致性。也就是說(shuō)ACID四大特性之中,C(一致性)是目的,A(原子性)、I(隔離性)、D(持久性)是手段,是為了保證一致性,數(shù)據(jù)庫(kù)提供的手段。數(shù)據(jù)庫(kù)必須要實(shí)現(xiàn)AID三大特性,才有可能實(shí)現(xiàn)一致性。例如,原子性無(wú)法保證,顯然一致性也無(wú)法保證。

但是,如果你在事務(wù)里故意寫出違反約束的代碼,一致性還是無(wú)法保證的。例如,你在轉(zhuǎn)賬的例子中,你的代碼里故意不給B賬戶加錢,那一致性還是無(wú)法保證。因此,還必須從應(yīng)用層角度考慮。

從應(yīng)用層面,通過(guò)代碼判斷數(shù)據(jù)庫(kù)數(shù)據(jù)是否有效,然后決定回滾還是提交數(shù)據(jù)!

問(wèn)題二: Mysql怎么保證原子性的?

OK,是利用Innodb的undo log。

undo log名為回滾日志,是實(shí)現(xiàn)原子性的關(guān)鍵,當(dāng)事務(wù)回滾時(shí)能夠撤銷所有已經(jīng)成功執(zhí)行的sql語(yǔ)句,他需要記錄你要回滾的相應(yīng)日志信息。

例如

  • (1)當(dāng)你delete一條數(shù)據(jù)的時(shí)候,就需要記錄這條數(shù)據(jù)的信息,回滾的時(shí)候,insert這條舊數(shù)據(jù)
  • (2)當(dāng)你update一條數(shù)據(jù)的時(shí)候,就需要記錄之前的舊值,回滾的時(shí)候,根據(jù)舊值執(zhí)行update操作
  • (3)當(dāng)年insert一條數(shù)據(jù)的時(shí)候,就需要這條記錄的主鍵,回滾的時(shí)候,根據(jù)主鍵執(zhí)行delete操作

undo log記錄了這些回滾需要的信息,當(dāng)事務(wù)執(zhí)行失敗或調(diào)用了rollback,導(dǎo)致事務(wù)需要回滾,便可以利用undo log中的信息將數(shù)據(jù)回滾到修改之前的樣子。

ps:具體的undo log日志長(zhǎng)啥樣,這個(gè)可以寫一篇文章了。而且寫出來(lái),看的人也不多,姑且先這么簡(jiǎn)單的理解吧。

問(wèn)題三: Mysql怎么保證持久性的?

OK,是利用Innodb的redo log。

正如之前說(shuō)的,Mysql是先把磁盤上的數(shù)據(jù)加載到內(nèi)存中,在內(nèi)存中對(duì)數(shù)據(jù)進(jìn)行修改,再刷回磁盤上。如果此時(shí)突然宕機(jī),內(nèi)存中的數(shù)據(jù)就會(huì)丟失。

怎么解決這個(gè)問(wèn)題?

簡(jiǎn)單啊,事務(wù)提交前直接把數(shù)據(jù)寫入磁盤就行啊。

這么做有什么問(wèn)題?

  • 只修改一個(gè)頁(yè)面里的一個(gè)字節(jié),就要將整個(gè)頁(yè)面刷入磁盤,太浪費(fèi)資源了。畢竟一個(gè)頁(yè)面16kb大小,你只改其中一點(diǎn)點(diǎn)東西,就要將16kb的內(nèi)容刷入磁盤,聽著也不合理。
  • 畢竟一個(gè)事務(wù)里的SQL可能牽涉到多個(gè)數(shù)據(jù)頁(yè)的修改,而這些數(shù)據(jù)頁(yè)可能不是相鄰的,也就是屬于隨機(jī)IO。顯然操作隨機(jī)IO,速度會(huì)比較慢。

于是,決定采用redo log解決上面的問(wèn)題。當(dāng)做數(shù)據(jù)修改的時(shí)候,不僅在內(nèi)存中操作,還會(huì)在redo log中記錄這次操作。當(dāng)事務(wù)提交的時(shí)候,會(huì)將redo log日志進(jìn)行刷盤(redo log一部分在內(nèi)存中,一部分在磁盤上)。當(dāng)數(shù)據(jù)庫(kù)宕機(jī)重啟的時(shí)候,會(huì)將redo log中的內(nèi)容恢復(fù)到數(shù)據(jù)庫(kù)中,再根據(jù)undo log和binlog內(nèi)容決定回滾數(shù)據(jù)還是提交數(shù)據(jù)。

采用redo log的好處?

其實(shí)好處就是將redo log進(jìn)行刷盤比對(duì)數(shù)據(jù)頁(yè)刷盤效率高,具體表現(xiàn)如下

  • redo log體積小,畢竟只記錄了哪一頁(yè)修改了啥,因此體積小,刷盤快。
  • redo log是一直往末尾進(jìn)行追加,屬于順序IO。效率顯然比隨機(jī)IO來(lái)的快。

ps:不想具體去談redo log具體長(zhǎng)什么樣,因?yàn)閮?nèi)容太多了。

問(wèn)題四: Mysql怎么保證隔離性的?

OK,利用的是鎖和MVCC機(jī)制。還是拿轉(zhuǎn)賬例子來(lái)說(shuō)明,有一個(gè)賬戶表如下

表名t_balance

id user_id balance
1 A 200
2 B 0

其中id是主鍵,user_id為賬戶名,balance為余額。還是以轉(zhuǎn)賬兩次為例,如下圖所示

至于MVCC,即多版本并發(fā)控制(Multi Version Concurrency Control),一個(gè)行記錄數(shù)據(jù)有多個(gè)版本對(duì)快照數(shù)據(jù),這些快照數(shù)據(jù)在undo log中。

如果一個(gè)事務(wù)讀取的行正在做DELELE或者UPDATE操作,讀取操作不會(huì)等行上的鎖釋放,而是讀取該行的快照版本。

由于MVCC機(jī)制在可重復(fù)讀(Repeateable Read)和讀已提交(Read Commited)的MVCC表現(xiàn)形式不同,就不贅述了。

但是有一點(diǎn)說(shuō)明一下,在事務(wù)隔離級(jí)別為讀已提交(Read Commited)時(shí),一個(gè)事務(wù)能夠讀到另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù),是不滿足隔離性的。但是當(dāng)事務(wù)隔離級(jí)別為可重復(fù)讀(Repeateable Read)中,是滿足隔離性的。

總結(jié)

本文講了Mysql中事務(wù)ACID四大特性的實(shí)現(xiàn)原理,希望大家有所收獲。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

您可能感興趣的文章:
  • MySQL如何實(shí)現(xiàn)事務(wù)的ACID
  • MySQL令人大跌眼鏡的隱式轉(zhuǎn)換
  • MySQL非空約束(not null)案例講解
  • 解決mysql數(shù)據(jù)庫(kù)數(shù)據(jù)遷移達(dá)夢(mèng)數(shù)據(jù)亂碼問(wèn)題
  • MySQL連接異常報(bào)10061錯(cuò)誤問(wèn)題解決
  • MySQL事務(wù)控制流與ACID特性

標(biāo)簽:駐馬店 陜西 鄂爾多斯 北京 荊門 黔西 梅河口 昌都

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Mysql中事務(wù)ACID的實(shí)現(xiàn)原理詳解》,本文關(guān)鍵詞  Mysql,中,事務(wù),ACID,的,實(shí)現(xiàn),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Mysql中事務(wù)ACID的實(shí)現(xiàn)原理詳解》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于Mysql中事務(wù)ACID的實(shí)現(xiàn)原理詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    介休市| 钟山县| 淅川县| 溧阳市| 九寨沟县| 乌审旗| 阿瓦提县| 保定市| 加查县| 西畴县| 茌平县| 图木舒克市| 佛学| 砀山县| 镇远县| 颍上县| 余干县| 乐都县| 蒲城县| 建瓯市| 泽库县| 富川| 吉木乃县| 昌黎县| 盐源县| 五指山市| 噶尔县| 江油市| 简阳市| 雅安市| 麻栗坡县| 陵水| 都匀市| 长泰县| 印江| 玛沁县| 西充县| 九台市| 古田县| 兴义市| 太仆寺旗|