MYSQL(02)-事務(wù)原理

ACID模型

MYSQL傳統(tǒng)關(guān)系數(shù)據(jù)庫的ACID模型有以下特性

  • Atomicity原子性:一個事務(wù)中所有操作都必須全部完成,要么全部不完成。
  • Consistency一致性. 在事務(wù)開始或結(jié)束時,數(shù)據(jù)庫應(yīng)該在一致狀態(tài)。
  • Isolation隔離性. 事務(wù)將假定只有它自己在操作數(shù)據(jù)庫,彼此不知曉。
  • Durability持久性.一旦事務(wù)完成,就不能返回。

MYSQL-ACID模型的實現(xiàn)原理如下

  • 事務(wù)的原子性是通過 undo log 來實現(xiàn)的
  • 事務(wù)的持久性性是通過 redo log 來實現(xiàn)的
  • 事務(wù)的隔離性是通過 (讀寫鎖+MVCC)來實現(xiàn)的
  • 而事務(wù)的終極大 boss 一致性是通過原子性,持久性,隔離性來實現(xiàn)的!?。?/li>

下面就逐一介紹其實現(xiàn)原理

原子性(Atomicity)原理

一個事務(wù)必須被視為不可分割的最小工作單位,一個事務(wù)中的所有操作要么全部成功提交,要么全部失敗回滾,對于一個事務(wù)來說不可能只執(zhí)行其中的部分操作,這就是事務(wù)的原子性。

數(shù)據(jù)庫是通過回滾操作來實現(xiàn)原子性的。 所謂回滾操作就是當發(fā)生錯誤異?;蛘唢@式的執(zhí)行rollback語句時需要把數(shù)據(jù)還原到原先的模樣,所以這時候就需要用到undo log來進行回滾。undo log 就是用于記錄更新或新增操作之前的數(shù)據(jù)狀態(tài),當出現(xiàn)需要回滾的情況時,將原數(shù)據(jù)刷回到數(shù)據(jù)庫中,從而保證操作的原子性,具體實現(xiàn)方式如下:

上面從銀行賬戶轉(zhuǎn)賬到理財賬戶的操作步驟如下

  • 1.事務(wù)開始
  • 2.查詢數(shù)據(jù)
  • 3.進行update操作,balance=balance-400;
  • 4.記錄zhangsan(1000)到undo log 日志中,回滾時需要將數(shù)據(jù)更新回來
  • 5.進行update操作,amount=amount+400;
  • 6.記錄amount(0)到undo log日志中,回滾的時候需要將數(shù)據(jù)刷新回來
  • 7.事務(wù)提交/回滾

持久性(Durability)原理

事務(wù)一旦提交,其所作做的修改會永久保存到數(shù)據(jù)庫中,此時即使系統(tǒng)崩潰修改的數(shù)據(jù)也不會丟失。
MySQL的數(shù)據(jù)存儲,表數(shù)據(jù)是存放在磁盤上的,因此想要存取的時候都要經(jīng)歷磁盤IO,然而即使是使用SSD磁盤IO也是非常消耗性能的。 為此,為了提升性能InnoDB提供了緩沖池(Buffer Pool),Buffer Pool中包含了磁盤數(shù)據(jù)頁的映射,可以當做緩存來使用:

  • 讀數(shù)據(jù):會首先從緩沖池中讀取,如果緩沖池中沒有,則從磁盤讀取在放入緩沖池;
  • 寫數(shù)據(jù):會首先寫入緩沖池,緩沖池中的數(shù)據(jù)會定期同步到磁盤中;

上面這種緩沖池的措施雖然在性能方面帶來了質(zhì)的飛躍,但是它也帶來了新的問題,當MySQL系統(tǒng)宕機,斷電的時候可能會丟數(shù)據(jù)!因為我們的數(shù)據(jù)已經(jīng)提交了,但此時是在緩沖池里頭,還沒來得及在磁盤持久化,所以我們急需一種機制需要存一下已提交事務(wù)的數(shù)據(jù),為恢復(fù)數(shù)據(jù)使用。redo log就派上用場了。

redo log來記錄已成功提交事務(wù)的修改信息,并且會把redo log持久化到磁盤,系統(tǒng)重啟之后在讀取redo log恢復(fù)最新數(shù)據(jù)。

隔離性(Isolation)原理

Mysql 隔離級別有以下四種(級別由低到高):

  • READ UNCOMMITED (讀未提交)
  • READ COMMITED (讀提交)
  • REPEATABLE READ (可重復(fù)讀)
  • SERIALIZABLE (串行化)

隔離性是要管理多個并發(fā)讀寫請求的訪問順序。 這種順序包括串行或者是并行,從隔離性的實現(xiàn)可以看出這是一場數(shù)據(jù)的可靠性與性能之間的權(quán)衡,可靠性性高的,并發(fā)性能低(比如 Serializable),可靠性低的,并發(fā)性能高(比如 Read Uncommited),不同的隔離級別會有不同的問題

- 臟讀 不可重復(fù)讀 幻讀
讀未提交
讀已提交 ×
不可重復(fù)讀 × ×
串行化 × × ×
  • 臟讀:事務(wù)中讀取到了其他事務(wù)沒有提交的數(shù)據(jù),主要是讀寫完全沒有加鎖造成的
  • 不可重復(fù)讀:事務(wù)中多次讀取結(jié)果不一致,因為多次讀取中間,其他事務(wù)修改并提交了數(shù)據(jù)(主要原因是修改)
  • 幻讀:事務(wù)中多次范圍讀取結(jié)果不一致,因為多次讀取中間,其他事務(wù)修改并提交了數(shù)據(jù)(主要原因是新增/刪除)

讀未提交(READ UNCOMMITED)

\color{red}{概念}:在該隔離級別下,事務(wù)中的修改即使還沒提交,對其他事務(wù)是可見的。其他事務(wù)可以讀取其未提交的數(shù)據(jù),造成臟讀。\color{red}{原理}:因為讀不會加任何鎖,所以寫操作在讀的過程中修改數(shù)據(jù),所以會造成臟讀。好處是可以提升并發(fā)處理性能,能做到讀寫并行。

讀提交(READ COMMITTED)

\color{red}{概念}:在該隔離級別下,事務(wù)中的修改如果還沒提交,對其他事務(wù)是不可見的。不會造成臟讀,但是多次讀取會造成數(shù)據(jù)不一致的情況,會有不可重復(fù)度的問題,例如:一個事務(wù)中兩次讀取,在這中間他事務(wù)進行了一個更新并提交,那么兩次讀取的內(nèi)容會不一樣。\color{red}{原理}:InnoDB在該隔離級別下讀取數(shù)據(jù)不加鎖而是使用了MVCC機制(詳情如下)

可重復(fù)讀 (REPEATABLE READ)

Mysql\color{red}{默認}隔離級別。在一個事務(wù)內(nèi)的多次讀取的結(jié)果是一樣的。這種級別下可以避免,臟讀,不可重復(fù)讀等查詢問題,Innodb可以解決還可以解決幻讀問題。Mysql 有兩種機制可以達到這種隔離級別的效果,分別是采用讀寫鎖和MVCC機制來實現(xiàn)。

  • 采用MVCC的實現(xiàn):使用\color{red}{快照讀} 的方式支持并行讀寫并行內(nèi)部使用MVCC原理(后面介紹)
  • 采用鎖的實現(xiàn):使用\color{red}{當前讀} 對于SELECT... FOR UPDATE ,SELECT ... LOCK IN SHARE MODE 等情況使用的是加鎖解決機制(記錄鎖,間隙鎖等實現(xiàn))

串行化(SERIALIZABLE)

  • 該隔離級別理解起來最簡單,實現(xiàn)也最單。在隔離級別下除了不會造成數(shù)據(jù)不一致問題,沒其他優(yōu)點。

MVCC (多版本控制)

MVCC (MultiVersion Concurrency Control) 叫做多版本并發(fā)控制,主要是針對事務(wù)中并行普通讀取的優(yōu)化。
InnoDB在實現(xiàn)的 MVCC的時候使用一致性視圖來保證RC(讀提交),和RR(可重復(fù)讀)事務(wù)隔離級別的實現(xiàn) ,\color{red}{原理}是事務(wù)開啟時,對整個庫創(chuàng)建快照(read view),是通過每行記錄的后面保存兩個隱藏的列來實現(xiàn)的。這兩個列, 一個保存了行的創(chuàng)建時間,一個保存了行的過期時間, 當然存儲的并不是實際的時間值,而是系統(tǒng)版本號。每當修改數(shù)據(jù)時,版本號加一。當事務(wù)讀取時,如果數(shù)據(jù)的當前版本號大于自己的事務(wù),則查詢的時候拋棄。從而實現(xiàn)不加鎖讀進而做到讀寫并行。MVCC在mysql中的實現(xiàn)依賴的是undo log與read view

  • undo log :undo log 中記錄某行數(shù)據(jù)的多個版本的數(shù)據(jù)。
  • read view :用來判斷當前版本數(shù)據(jù)的可見性

在不同的隔離級別下,MVCC創(chuàng)建read view歷史版本的時機也是不同的

  • 在讀提交隔離級別下:視圖 read-view的創(chuàng)建是在語句執(zhí)行的時候創(chuàng)建的
  • 在可重復(fù)讀隔離級別下:視圖 read-view的創(chuàng)建是在事務(wù)啟動的時候創(chuàng)建的

幻讀問題詳解

幻讀在業(yè)務(wù)中存在兩種情況,快照讀,和當前讀,MVCC策略能夠解決快照讀的問題,但是對于當前讀則需要使用間隙鎖。\color{red}{當前讀}是指讀取數(shù)據(jù)庫中最新版本的數(shù)據(jù),在多個update的時候不能基于快照讀。讀取歷史版本的數(shù)據(jù)進行更新,會導(dǎo)致數(shù)據(jù)不一致問題

  • 快照讀:當使用普通select * 進行統(tǒng)計的時候,使用MVCC可以保證幻讀問題
  • 當前讀:當使用select for update 或者 select ... lock in share mode 操作的時候,insert,update,delete等操作都會被阻塞。當前讀是通過手動加record lock(記錄鎖)和gap lock(間隙鎖 )來實現(xiàn)的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、事務(wù) 1、事務(wù)四要素:ACID 對于事務(wù),我之前的理解是很粗糙的,不就是為了保證操作的原子性么?一般訂單系統(tǒng)或...
    張偉科閱讀 1,499評論 0 5
  • 什么是事務(wù) 事務(wù)是一條或多條數(shù)據(jù)庫操作語句的組合,具備ACID,4個特點。 原子性:要不全部成功,要不全部撤銷 隔...
    jiangmo閱讀 1,200評論 0 3
  • 事務(wù)原理: 為了支持事務(wù),Innodb引入了下面幾個概念: 一、MYSQL 日志介紹: 1.binlog binl...
    極簡架構(gòu)閱讀 2,125評論 4 20
  • 事務(wù)(Transaction)是數(shù)據(jù)庫區(qū)別于文件系統(tǒng)的重要特性之一。 在文件系統(tǒng)中, 如果正在寫文件, 但是操作系...
    好好學(xué)習Sun閱讀 1,147評論 0 5
  • 去年八月末來到了承醫(yī),這個遠方。 僅希望2017能遇見最好的自己,等我長成一棵大樹,等你贊一聲良木。
    黃三歲w閱讀 316評論 0 0

友情鏈接更多精彩內(nèi)容