MYSQL事務

事務簡介

    事務是數據庫區別於文件系統的最重要特徵之一。事務可以保證數據庫從一個狀態轉移到另一個狀態,也就是說在一個事務中的語句要麼全部一起提交(所有修改都會保存),要麼回滾(所有修改都不會保存)。

    事務的性質:原子性,一致性,隔離性,持久性(ACID)保證一個事務的正確執行。每種性質具體含義具體參考:https://blog.csdn.net/puliao4167/article/details/89043612

事務的分類

    事務可以分爲扁平事務,帶有保存點的扁平事務,鏈事務,嵌套事務,分佈式事務

  • 扁平事務,是平常用的最多的事務,所有的操作處於同一個層次,由begin開始,由commit或者rollback結束,其間的操作語句都是原子性的,要麼都執行,要麼都不執行。
  • 帶有保存點的扁平事務,除了支持扁平的事務外,還允許在回滾的時候,可以回滾到同一事物的較早的狀態,保存點是用來提醒系統記住當前的狀態。如果沒有特殊的(顯式的)保存點,在回滾的時候默認會回滾到事務起始處,
  • 鏈事務,可以視爲保存點模式的另一種方式,帶有保存點的扁平事務中的保存點是易失的,而非持久的,當系統發生崩潰時,保存點即會消失,事務要從頭開始執行。鏈事務的思想是:在提交一個事務的時候,釋放不需要的數據,將要處理的上下文隱式的傳遞給下一個開啓的事務(形成一個鏈狀)
  • 嵌套事務是一個層次結構框架,一個頂級事務中調用子事務
  • 分佈式事務是在分佈式的環境下運行的扁平事務

redo日誌

    首要要清楚,事務ACID中的隔離性是由鎖機制來實現的,而另外的三個性質原子性,持久性,一致性由redo日誌,undo日誌保證。

    redo log(重做日誌)是有兩個部分組成:一個是在內存中的重做日誌緩衝,另一個是在磁盤中的重做日誌文件。在InnoDB存儲引擎中,大部分情況下 Redo是物理日誌,記錄的是數據頁的物理變化。Redo log的主要作用是用於數據庫的崩潰恢復。redo的流程如下:

  1. 先將原始數據從磁盤中讀入內存中來,修改數據的內存拷貝
  2. 生成一條重做日誌並寫入redo log buffer,記錄的是數據被修改後的值
  3. 當事務commit時,將redo log buffer中的內容刷新到 redo log file,對 redo log file採用追加寫(順序寫)的方式
  4. 定期將內存中修改的數據刷新到磁盤中

    從上圖中可以看出,Innodb其通過Force Log at Commit 機制實現事務的持久性,即當事務提交時,先將 redo log buffer 寫入到 redo log file 進行持久化,待事務的commit操作完成時纔算完成。這種做法也被稱爲 Write-Ahead Log(預先日誌持久化),在持久化一個數據頁之前,先將內存中相應的日誌頁持久化。

    Force Log at Commit機制就是靠InnoDB存儲引擎提供的參數 innodb_flush_log_at_trx_commit來控制的,該參數可以控制 redo log刷新到磁盤的策略,設置該參數值也可以允許用戶設置非持久性的情況發生,具體如下:

  • 當設置參數爲1時,(默認爲1),表示事務提交時必須調用一次fsync操作,最安全的配置,保障持久性
  • 當設置參數爲2時,則在事務提交時只做write操作,只保證將redo log buffer寫到系統的頁面緩存中,不進行fsync操作,因此如果MySQL數據庫宕機時 不會丟失事務,但操作系統宕機則可能丟失事務
  • 當設置參數爲0時,表示事務提交時不進行寫入redo log操作,這個操作僅在master thread 中完成,而在master thread中每1秒進行一次重做日誌的fsync操作,因此實例 crash 最多丟失1秒鐘內的事務。(master thread是負責將緩衝池中的數據異步刷新到磁盤,保證數據的一致性)

undo日誌

    undo log主要記錄的是數據的邏輯變化,爲了在發生錯誤時回滾之前的操作,需要將之前的操作都記錄下來,然後在發生錯誤時纔可以回滾。redo log存放在內存的重做日誌文件中,undo 存放在數據庫中一個特殊的段中(undo 段),是一種邏輯日誌。undo有兩個作用,一是記錄操作用於事務回滾,第二是MVCC。在回滾的時候,它實際上是做的相反的工作,比如一條INSERT ,對應一條 DELETE,對於每個UPDATE,對應一條相反的 UPDATE,將修改前的行放回去,所以其要在DML語句修改之前記錄數據。

    當進行insert或者update修改聚簇索引前,要記錄undo日誌,需要注意的是,記錄undo日誌,同時也要記錄redo日誌。以下一個例子

假設有A、B兩個數據,值分別爲1,2.
1. 事務開始
2. 記錄A=1到undo log
3. 修改A=3
4. 記錄A=3到 redo log
5. 記錄B=2到 undo log
6. 修改B=4
7. 記錄B=4到redo log
8. 將redo log寫入磁盤
9. 事務提交

 

參考《高性能mysql》、《MYSQL技術內幕 Innodb存儲引擎》

淺談mysql事務中的redo和undo  https://www.jianshu.com/p/20e10ed721d0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章