天天看點

mysql innodb 事務_MySQL的InnoDB的事務

事務是資料庫最為重要的機制之一,凡是使用過資料庫的人,都了解資料庫的事務機制,也對ACID四個基本特性如數家珍。但是聊起事務或者ACID的底層實作原理,往往言之不詳,不明是以。是以,今天我們就一起來分析和探讨InnoDB的事務機制,希望能建立起對事務底層實作原理的具體了解。

mysql innodb 事務_MySQL的InnoDB的事務

資料庫事務具有ACID四大特性。ACID是以下4個詞的縮寫:

原子性(atomicity):事務最小工作單元,要麼全成功,要麼全失敗。

一緻性(consistency):事務開始和結束後,資料庫的完整性不會被破壞。

隔離性(isolation):不同僚務之間互不影響,四種隔離級别為RU(讀未送出)、RC(讀已送出)、RR(可重複讀)、SERIALIZABLE(串行化)。

持久性(durability):事務送出後,對資料的修改是永久性的,即使系統故障也不會丢失。

下面,我們就以一個具體執行個體來介紹資料庫事務的原理,并介紹InnoDB是如何實作ACID四大特性的。

示例介紹

我們首先來看一下具體的示例。大家可以自己親自試驗一下,這樣了解和記憶都會更加深刻。

首先,使用如下的SQL語句建立兩張表,分别是goods和trade,代表貨物和交易。并向goods表中插入一條記錄,id為1的貨物數量為10。

CREATETABLEgoods(idINT,numINT,PRIMARYKEY(id));

CREATETABLEtrade(idINT,goods_idINT,user_idINT,PRIMARYKEY(id));

INSERTINTOgoodsVALUES(1,10);

然後打開終端,連接配接資料庫,開啟會話一,先用BEGIN顯示開啟一個事務。會話一先将goods表中id為1的貨物的數量減一,然後向trade表中添加一筆交易的記錄,最後使用COMMIT顯示送出事務。

而會話二則先查詢goods表中id為1的貨物數量,然後向trade表中添加一筆交易記錄,接着更新goods表中id為1的貨物的數量,最後使用ROLLBACK進行事務的復原。其中,兩個會話中執行的具體語句和先後順序如下圖所示。

mysql innodb 事務_MySQL的InnoDB的事務

這個示例可以展現資料庫事務的很多特性,我們一一來介紹。首先會話一的操作2更新了id為1的貨物的數量,但是會話二的操作5讀出來的數量仍然是10,這展現了事務的隔離性,使用InnoDB的多版本控制機制實作。

會話二的操作7也要更新同種貨物的數量,此時因為會話一的操作2已經更新了該貨物的數量,InnoDB已經鎖住了該記錄的行鎖,是以操作7會被阻塞,直到會話一COMMIT。但是會話一的操作4和會話二的操作7都是向trade表中插入記錄,後者卻不會因為前者而阻塞,因為二者插入的不是同一行記錄。鎖機制是一種常見的并發控制機制,它和多版本控制機制一起實作了InnoDB事務的隔離性,關于InnoDB鎖相關的具體内容可以參考InnoDB鎖的類型和狀态查詢和InnoDB行鎖算法。

會話一事務最終使用COMMIT送出了事務而會話二事務則使用ROLLBACK復原了整個事務,這展現了事務的原子性。即事務的一系列操作要麼全部執行(COMMIT),要麼就全部不執行(ROLLBACK),不存在隻執行一部分的情況。InnoDB使用事務日志系統來實作事務的原子性。這裡有的同學就會問了,如果中途連接配接斷開或者ServerCrash會怎麼樣。能怎麼樣,直接自動復原呗。

一旦會話一使用COMMIT操作送出事務成功後,那麼資料一定會被寫入到資料庫中并持久的存儲起來,這展現了事務的持久性。InnoDB使用redolog機制來實作事務的持久性。

而事務的一緻性比較難以了解,簡單的講在事務開始時,此時資料庫有一種狀态,這個狀态是所有的MySQL對象處于一緻的狀态,例如資料庫完整性限制正确,日志狀态一緻等。當事務送出後,這時資料庫又有了一個新的狀态,不同的資料,不同的索引,不同的日志等。但此時,限制,資料,索引,日志等MySQL各種狀态還是要保持一緻性。也就是說資料庫從一個一緻性的狀态,變到另一個一緻性的狀态。事務執行後,并沒有破壞資料庫的完整性限制。

下面我們就來詳細講解一下上述示例涉及的事務的ACID特性的具體實作原理。總結來說,事務的隔離性由多版本控制機制和鎖實作,而原子性、一緻性和持久性通過InnoDB的redolog、undolog和ForceLogatCommit機制來實作。

原子性,持久性和一緻性

原子性,持久性和一緻性主要是通過redolog、undolog和ForceLogatCommit機制機制來完成的。redolog用于在崩潰時恢複資料,undolog用于對事務的影響進行撤銷,也可以用于多版本控制。而ForceLogatCommit機制保證事務送出後redolog日志都已經持久化。

開啟一個事務後,使用者可以使用COMMIT來送出,也可以用ROLLBACK來復原。其中COMMIT或者ROLLBACK執行成功之後,資料一定是會被全部儲存或者全部復原到最初狀态的,這也展現了事務的原子性。但是也會有很多的異常情況,比如說事務執行中途連接配接斷開,或者是執行COMMIT或者ROLLBACK時發生錯誤,ServerCrash等,此時資料庫會自動進行復原或者重新開機之後進行恢複。

我們先來看一下redolog的原理,redolog顧名思義,就是重做日志,每次資料庫的SQL操作導緻的資料變化它都會記錄一下,具體來說,redolog是實體日志,記錄的是資料庫頁的實體修改操作。如果資料發生了丢失,資料庫可以根據redolog進行資料恢複。

InnoDB通過ForceLogatCommit機制實作事務的持久性,即當事務COMMIT時,必須先将該事務的所有日志都寫入到redolog檔案進行持久化之後,COMMIT操作才算完成。

當事務的各種SQL操作執行時,即會在緩沖區中修改資料,也會将對應的redolog寫入它所屬的緩存。當事務執行COMMIT時,與該事務相關的redolog緩沖必須都全部重新整理到磁盤中之後COMMIT才算執行成功。

mysql innodb 事務_MySQL的InnoDB的事務

redolog寫入磁盤時,必須進行一次作業系統的fsync操作,防止redolog隻是寫入了作業系統的磁盤緩存中。參數innodbflushlogattrx_commit可以控制redolog日志重新整理到磁盤的政策,它的具體作用可以查閱InnoDB的磁盤檔案及落盤機制

redolog全部寫入磁盤後事務就算COMMIT成功了,但是此時事務修改的資料還在記憶體的緩沖區中,稱其為髒頁,這些資料會依據檢查點(CheckPoint)機制擇時重新整理到磁盤中,然後删除相應的redolog,但是如果在這個過程中資料庫Crash了,那麼資料庫重新開機時,會依據redologfile将那些還在記憶體中未更新到磁盤上的資料進行恢複。

資料庫為了提高性能,資料頁在記憶體修改後并不是每次都會刷到磁盤上。而是引入checkpoint機制,擇時将資料頁落盤,checkpoint記錄之前的資料頁保證一定落盤了,這樣相關的redolog就沒有用了(由于InnoDBredologfile循環使用,這時這部分日志就可以被覆寫),checkpoint之後的資料頁有可能落盤,也有可能沒有落盤,是以checkpoint之後的redologfile在崩潰恢複的時候還是需要被使用的。InnoDB會依據髒頁的重新整理情況,定期推進checkpoint,進而減少資料庫崩潰恢複的時間。檢查點的資訊在第一個日志檔案的頭部。

資料庫崩潰重新開機後需要從redolog中把未落盤的髒頁資料恢複出來,重新寫入磁盤,保證使用者的資料不丢失。當然,在崩潰恢複中還需要復原沒有送出的事務。由于復原操作需要undo日志的支援,undo日志的完整性和可靠性需要redo日志來保證,是以崩潰恢複先做redo恢複資料,然後做undo復原。

在事務執行的過程中,除了記錄redolog,還會記錄一定量的undolog。undolog記錄了資料在每個操作前的狀态,如果事務執行過程中需要復原,就可以根據undolog進行復原操作。

mysql innodb 事務_MySQL的InnoDB的事務

undolog的存儲不同于redolog,它存放在資料庫内部的一個特殊的段(segment)中,這個段稱為復原段。復原段位于共享表空間中。undo段中的以undopage為更小的組織機關。undopage和存儲資料庫資料和索引的頁類似。因為redolog是實體日志,記錄的是資料庫頁的實體修改操作。是以undolog的寫入也會産生redolog,也就是undolog的産生會伴随着redolog的産生,這是因為undolog也需要持久性的保護。如上圖所示,表空間中有復原段和葉節點段和非葉節點段,而三者都有對應的頁結構。

我們再來總結一下資料庫事務的整個流程,如下圖所示。

mysql innodb 事務_MySQL的InnoDB的事務

事務進行過程中,每次sql語句執行,都會記錄undolog和redolog,然後更新資料形成髒頁,然後redolog按照時間或者空間等條件進行落盤,undolog和髒頁按照checkpoint進行落盤,落盤後相應的redolog就可以删除了。此時,事務還未COMMIT,如果發生崩潰,則首先檢查checkpoint記錄,使用相應的redolog進行資料和undolog的恢複,然後檢視undolog的狀态發現事務尚未送出,然後就使用undolog進行事務復原。事務執行COMMIT操作時,會将本事務相關的所有redolog都進行落盤,隻有所有redolog落盤成功,才算COMMIT成功。然後記憶體中的資料髒頁繼續按照checkpoint進行落盤。如果此時發生了崩潰,則隻使用redolog恢複資料。

隔離性

InnoDB事務的隔離性主要通過多版本控制機制和鎖機制實作,具體可以參考多版本控制,InnoDB鎖的類型和狀态查詢和InnoDB行鎖算法三篇文章。