欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2019年05月10日 14:48:39   作者:孤獨煙  
這篇文章主要給大家介紹了關于Mysql中事務ACID實現(xiàn)原理的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Mysql具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

引言

照例,我們先來一個場景~

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

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

正文

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

原子性

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

如果無法保證原子性會怎么樣?

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

隔離性

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

如果無法保證隔離性會怎么樣?

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


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

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

持久性

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

如果無法保證持久性會怎么樣?

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

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

一致性

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

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

如果無法保證一致性會怎么樣?

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

例二:A賬戶200元,轉(zhuǎn)賬50元給B賬戶,A賬戶的錢扣了,但是B賬戶因為各種意外,余額并沒有增加。你也知道此時數(shù)據(jù)是不一致的,為什么呢?因為你定義了一個狀態(tài),要求A+B的余額必須不變。

實戰(zhàn)解答

問題一:Mysql怎么保證一致性的?

OK,這個問題分為兩個層面來說。

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

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

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

問題二: Mysql怎么保證原子性的?

OK,是利用Innodb的undo log。

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

例如

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

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

ps:具體的undo log日志長啥樣,這個可以寫一篇文章了。而且寫出來,看的人也不多,姑且先這么簡單的理解吧。

問題三: Mysql怎么保證持久性的?

OK,是利用Innodb的redo log。

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

怎么解決這個問題?

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

這么做有什么問題?

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

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

采用redo log的好處?

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

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

ps:不想具體去談redo log具體長什么樣,因為內(nèi)容太多了。

問題四: Mysql怎么保證隔離性的?

OK,利用的是鎖和MVCC機制。還是拿轉(zhuǎn)賬例子來說明,有一個賬戶表如下

表名t_balance

id user_id balance
1 A 200
2 B 0

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

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

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

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

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

總結

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

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

相關文章

  • 淺談MySQL大表優(yōu)化方案

    淺談MySQL大表優(yōu)化方案

    這篇文章主要介紹了淺談MySQL大表優(yōu)化方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • MySQL優(yōu)化GROUP BY(松散索引掃描與緊湊索引掃描)

    MySQL優(yōu)化GROUP BY(松散索引掃描與緊湊索引掃描)

    這篇文章主要介紹了MySQL優(yōu)化GROUP BY(松散索引掃描與緊湊索引掃描),需要的朋友可以參考下
    2016-05-05
  • MySQL查詢中LIMIT的大offset導致性能低下淺析

    MySQL查詢中LIMIT的大offset導致性能低下淺析

    這篇文章主要給大家介紹了關于MySQL查詢中LIMIT的大offset導致性能低下的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-12-12
  • MySQL  Lock wait timeout exceeded錯誤解決

    MySQL  Lock wait timeout exceeded錯誤

    “Lock wait timeout exceeded” 是一個常見的MySQL錯誤,指示了潛在的性能問題或死鎖,本文就來介紹一下如何解決,感興趣的可以了解一下
    2024-05-05
  • 基于unique與primary約束的區(qū)別分析

    基于unique與primary約束的區(qū)別分析

    本篇文章介紹了unique與primary約束的區(qū)別分析。需要的朋友參考下
    2013-04-04
  • mysql8.0.0 winx64.zip解壓版安裝配置教程

    mysql8.0.0 winx64.zip解壓版安裝配置教程

    這篇文章主要為大家詳細介紹了mysql8.0.0 winx64.zip解壓版安裝配置教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 一條 SQL 語句執(zhí)行過程

    一條 SQL 語句執(zhí)行過程

    這篇文章主要介紹了一條 SQL 語句執(zhí)行過程的相關資料,沒人詳細具有一的的參考價值,需要的小伙伴可以參考一下,希望對你的學習和工作有所幫助
    2022-03-03
  • Linux mysql命令安裝允許遠程連接的安裝設置方法

    Linux mysql命令安裝允許遠程連接的安裝設置方法

    對大家推薦很好使用的Linux mysql系統(tǒng),像讓大家對Linux mysql系統(tǒng)有所了解,然后對Linux mysql系統(tǒng)全面講解介紹,希望對大家有用今天特意配置了mysql apache php ,雖然網(wǎng)上很多這方面的例子,但是很多是作者再回憶寫的,所以難免有筆誤的地方。
    2010-08-08
  • 在Docker中使用MySQL的教程

    在Docker中使用MySQL的教程

    這篇文章主要介紹了在Docker中使用MySQL的教程,介紹了簡單的內(nèi)部搭建步驟,需要的朋友可以參考下
    2015-04-04
  • MySQL學習之事務詳解

    MySQL學習之事務詳解

    在數(shù)據(jù)庫中?事務(transaction)?可以把多個SQL給打包到一起,?即將多個SQL語句變成一個整體,?也就是說一個事務中的所有操作要么全部成功執(zhí)行,?要么完全不執(zhí)行.本文主要來和大家聊聊事務的使用,需要的可以參考一下
    2022-12-12

最新評論