說到數據庫,那就必定會聊到事務,事務也是面試中常問的問題,咱們先來一個面試場景:java
面試官:"事務的四大特性是什麼?"
我:"ACID,即原子性(Atomicity)、隔離性(Isolation)、持久性(Durability)、一致性(Consistency)!"
面試官:"在 MySQL 數據庫的 InnoDB 引擎是怎麼實現這四大特性的?"
我:"這個...這個....,還真沒有了解過哎"
面試官:"那咱們就先這個吧,先回去吧,咱們會通知你的~"
複製代碼
這多是比較常見的面試場景了,你也許回答到了事務的四大特性,可是不必定知道他的實現原理。今天咱們就來一塊兒打卡事務的四大特性和實現原理,對於原理的實現,這篇文章只是粗略的介紹一下,更多的細節能夠關注我後續的文章。程序員
數據庫的事務有四大特性:原子性、隔離性、永久性、一致性,下面將介紹這四大特性的定義和在 InnoDB 引擎中是怎麼實現的。面試
一次操做是不可分割的,要麼所有成功,要麼所有失敗。好比咱們的轉帳操做,不容許出款方成功,收款方失敗這種狀況,要麼都成功,要麼多失敗,不可能出現中間狀態。數據庫
InnoDB 引擎使用 undo log(歸滾日誌)來保證原子性操做,你對數據庫的每一條數據的改動(INSERT、DELETE、UPDATE)都會被記錄到 undo log 中,好比如下這些操做:安全
當事務執行失敗或者調用了 rollback 方法時,就會觸發回滾事件,利用 undo log 中記錄將數據回滾到修改以前的樣子。微信
更多關於 undo log 的信息,後面再單獨開一篇文章打卡。併發
多個事務併發執行的時候,事務內部的操做與其餘事務是隔離的,併發執行的各個事務之間不能互相干擾。性能
隔離性可能會引入髒讀(dirty read)、不可重複讀(non-repeatable read)、幻讀(phantom read)等問題,爲了解決這些問題就引入了「隔離級別」的概念。學習
SQL 標準的事務隔離級別包括:讀未提交(read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(serializable):spa
SQL標準中規定,針對不一樣的隔離級別,併發事務能夠發生不一樣嚴重程度的問題,具體狀況以下:
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交 |
可能 | 可能 | 可能 |
讀提交 |
不可能 | 可能 | 可能 |
可重複讀 |
不可能 | 不可能 | 可能 |
串行化 |
不可能 | 不可能 | 不可能 |
上面就是幾種隔離級別可能出現的併發問題,可是有必要說一下,你隔離得越嚴實,效率就會越低。
InnoDB 引擎是如何保證隔離性的?利用鎖和 MVCC 機制。這裏簡單的介紹一下 MVCC 機制,也叫多版本併發控制,在使用 READ COMMITTD、REPEATABLE READ 這兩種隔離級別的事務下,每條記錄在更新的時候都會同時記錄一條回滾操做,就會造成一個版本鏈,在執行普通的 SELECT 操做時訪問記錄的版本鏈的過程,這樣子可使不一樣事務的讀-寫、寫-讀操做併發執行,從而提高系統性能。
事務一旦提交,它對數據庫的改變就應該是永久性的。接下來的其餘操做或故障不該該對其有任何影響。
要保證持久性很簡單,就是每次事務提交的時候,都將數據刷磁盤上,這樣必定保證了安全性,可是要知道若是每次事務提交都將數據寫入到磁盤的話,頻繁的 IO 操做,成本過高,數據庫的性能極低,因此這種方式不可取。
InnoDB 引擎是怎麼解決的?InnoDB 引擎引入了一箇中間層來解決這個持久性的問題,咱們把這個叫作 redo log(歸檔日子)。
爲何要引入 redo log?redo log 能夠保證持久化又能夠保證數據庫的性能,相比於直接刷盤,redo log 有如下兩個優點:
InnoDB 引擎是怎麼作的?當有一條記錄須要更新的時候,InnoDB 引擎就會先把記錄寫到 redo log 裏面,並更新內存,這個時候更新就算完成了。當數據庫宕機重啓的時候,會將 redo log 中的內容恢復到數據庫中,再根據 undo log和 binlog 內容決定回滾數據仍是提交數據。
更多 redo log,後面我打算單獨寫一篇文章。
一致性簡單一點說就是數據執行先後都要處於一種合法的狀態,好比身份證號不能重複,性別只能是男或者女,高考的分數只能在0~750之間,紅綠燈只有3種顏色,房價不能爲負的等等, 只有符合這些約束的數據纔是有效的,好比有個小孩兒跟你說他高考考了1000分,你一聽就知道他胡扯呢。數據庫世界只是現實世界的一個映射,現實世界中存在的約束固然也要在數據庫世界中有所體現。若是數據庫中的數據所有符合現實世界中的約束(all defined rules),咱們說這些數據就是一致的,或者說符合一致性的。
要保證數據庫的數據一致性,要在如下兩個方面作努力:
NOT NULL
來拒絕NULL
值得插入等。以上就是我今天要分享的內容,但願這篇文章對你的學習或者工做有所幫助,感謝您的閱讀,若是您以爲文章不錯歡迎點贊+轉發,感謝。
目前互聯網上不少大佬都有 MySQL 相關文章,若有雷同,請多多包涵了。原創不易,碼字不易,還但願你們多多支持。若文中有所錯誤之處,還望提出,謝謝。
歡迎掃碼關注微信公衆號:「平頭哥的技術博文」,和平頭哥一塊兒學習,一塊兒進步。