Mysql中事務ACID實現原理

2021-09-26 07:45:43 字數 2749 閱讀 2361

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

面試官:「知道事務的四大特性麼?」

你:「懂,acid嘛,原子性(atomicity)、一致性(consistency)、隔離性(isolation)、永續性(durability)!」

面試官:"你們是用mysql資料庫吧,能簡單說說innodb中怎麼實現這四大特性的麼?「

你:「我只知道隔離性是怎麼做的balabala~~」

面試官:「還是回去等通知吧~」

ok,回到正題。說到事務的四大特性原子性(atomicity)、一致性(consistency)、隔離性(isolation)、永續性(durability),懂的人很多。但是稍微涉及細節一點,這四大特性在資料庫中的實現原理是怎麼樣的?那就沒有幾個人能夠答得上來了。因此,我們這篇文章著重討論一下四大特性在mysql中的實現原理。

正文我們以從a賬戶轉賬50元到b賬戶為例進行說明一下acid,四大特性。

ps:可能有細心的讀者已經發現了,mysql中是依靠鎖來解決隔離性問題。嗯,我們後面來說明。

如果無法保證永續性會怎麼樣?

在mysql中,為了解決cpu和磁碟速度不一致問題,mysql是將磁碟上的資料載入到記憶體,對記憶體進行操作,然後再回寫磁碟。好,假設此時宕機了,在記憶體中修改的資料全部丟失了,永續性就無法保證。

設想一下,系統提示你轉賬成功。但是你發現金額沒有發生任何改變,此時資料出現了不合法的資料狀態,我們將這種狀態認為是資料不一致的情形。

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

例一:a賬戶有200元,轉賬300元出去,此時a賬戶餘額為-100元。你自然就發現了此時資料是不一致的,為什麼呢?因為你定義了乙個狀態,餘額這列必須大於0。

例二:a賬戶200元,轉賬50元給b賬戶,a賬戶的錢扣了,但是b賬戶因為各種意外,餘額並沒有增加。你也知道此時資料是不一致的,為什麼呢?因為你定義了乙個狀態,要求a+b的餘額必須不變。

實戰解答

問題一:mysql怎麼保證一致性的?

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

從資料庫層面,資料庫通過原子性、隔離性、永續性來保證一致性。也就是說acid四大特性之中,c(一致性)是目的,a(原子性)、i(隔離性)、d(永續性)是手段,是為了保證一致性,資料庫提供的手段。資料庫必須要實現aid三大特性,才有可能實現一致性。例如,原子性無法保證,顯然一致性也無法保證。

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

從應用層面,通過**判斷資料庫資料是否有效,然後決定回滾還是提交資料!

問題二: mysql怎麼保證原子性的?

ok,是利用innodb的undo log。

undo log名為回滾日誌,是實現原子性的關鍵,當事務回滾時能夠撤銷所有已經成功執行的sql語句,他需要記錄你要回滾的相應日誌資訊。例如

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

問題三: mysql怎麼保證永續性的?

ok,是利用innodb的redo log。

正如之前說的,mysql是先把磁碟上的資料載入到記憶體中,在記憶體中對資料進行修改,再刷回磁碟上。如果此時突然宕機,記憶體中的資料就會丟失。

怎麼解決這個問題?
簡單啊,事務提交前直接把資料寫入磁碟就行啊。
這麼做有什麼問題?

只修改乙個頁面裡的乙個位元組,就要將整個頁面刷入磁碟,太浪費資源了。畢竟乙個頁面16kb大小,你只改其中一點點東西,就要將16kb的內容刷入磁碟,聽著也不合理。

畢竟乙個事務裡的sql可能牽涉到多個資料頁的修改,而這些資料頁可能不是相鄰的,也就是屬於隨機io。顯然操作隨機io,速度會比較慢。

於是,決定採用redo log解決上面的問題。當做資料修改的時候,不僅在記憶體中操作,還會在redo log中記錄這次操作。當事務提交的時候,會將redo log日誌進行刷盤(redo log一部分在記憶體中,一部分在磁碟上)。當資料庫宕機重啟的時候,會將redo log中的內容恢復到資料庫中,再根據undo log和binlog內容決定回滾資料還是提交資料。

採用redo log的好處?

其實好處就是將redo log進行刷盤比對資料頁刷盤效率高,具體表現如下

問題四: mysql怎麼保證隔離性的?

ok,利用的是鎖和mvcc機制。還是拿轉賬例子來說明,有乙個賬戶表如下

表名 t_balance

iduser_id

balance1a

2002b0

其中id是主鍵,user_id為賬戶名,balance為餘額。還是以轉賬兩次為例,如下圖所示

至於mvcc,即多版本併發控制(multi version concurrency control),乙個行記錄資料有多個版本對快照資料,這些快照資料在undo log中。

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

由於mvcc機制在可重複讀(repeateable read)和讀已提交(read commited)的mvcc表現形式不同,就不贅述了。

但是有一點說明一下,在事務隔離級別為讀已提交(read commited)時,乙個事務能夠讀到另乙個事務已經提交的資料,是不滿足隔離性的。但是當事務隔離級別為可重複讀(repeateable read)中,是滿足隔離性的。

Mysql中事務ACID實現原理

照例,我們先來乙個場景 面試官 知道事務的四大特性麼?你 懂,acid嘛,原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durability 面試官 你們是用mysql資料庫吧,能簡單說說innodb中怎麼實現這四大特性的麼?你 我只知道隔離性是怎麼...

原創 Mysql中事務ACID實現原理

照例,我們先來乙個場景 面試官 知道事務的四大特性麼?你 懂,acid嘛,原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durability 面試官 你們是用mysql資料庫吧,能簡單說說innodb中怎麼實現這四大特性的麼?你 我只知道隔離性是怎麼...

原創 Mysql中事務ACID實現原理

照例,我們先來乙個場景 面試官 知道事務的四大特性麼?你 懂,acid嘛,原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durability 面試官 你們是用mysql資料庫吧,能簡單說說innodb中怎麼實現這四大特性的麼?你 我只知道隔離性是怎麼...