事務簡介
事務是數據庫區別於文件系統的最重要特徵之一。事務可以保證數據庫從一個狀態轉移到另一個狀態,也就是說在一個事務中的語句要麼全部一起提交(所有修改都會保存),要麼回滾(所有修改都不會保存)。
事務的性質:原子性,一致性,隔離性,持久性(ACID)保證一個事務的正確執行。每種性質具體含義具體參考:https://blog.csdn.net/puliao4167/article/details/89043612
事務的分類
事務可以分爲扁平事務,帶有保存點的扁平事務,鏈事務,嵌套事務,分佈式事務
- 扁平事務,是平常用的最多的事務,所有的操作處於同一個層次,由begin開始,由commit或者rollback結束,其間的操作語句都是原子性的,要麼都執行,要麼都不執行。
- 帶有保存點的扁平事務,除了支持扁平的事務外,還允許在回滾的時候,可以回滾到同一事物的較早的狀態,保存點是用來提醒系統記住當前的狀態。如果沒有特殊的(顯式的)保存點,在回滾的時候默認會回滾到事務起始處,
- 鏈事務,可以視爲保存點模式的另一種方式,帶有保存點的扁平事務中的保存點是易失的,而非持久的,當系統發生崩潰時,保存點即會消失,事務要從頭開始執行。鏈事務的思想是:在提交一個事務的時候,釋放不需要的數據,將要處理的上下文隱式的傳遞給下一個開啓的事務(形成一個鏈狀)
- 嵌套事務是一個層次結構框架,一個頂級事務中調用子事務
- 分佈式事務是在分佈式的環境下運行的扁平事務
redo日誌
首要要清楚,事務ACID中的隔離性是由鎖機制來實現的,而另外的三個性質原子性,持久性,一致性由redo日誌,undo日誌保證。
redo log(重做日誌)是有兩個部分組成:一個是在內存中的重做日誌緩衝,另一個是在磁盤中的重做日誌文件。在InnoDB存儲引擎中,大部分情況下 Redo是物理日誌,記錄的是數據頁的物理變化。Redo log的主要作用是用於數據庫的崩潰恢復。redo的流程如下:
- 先將原始數據從磁盤中讀入內存中來,修改數據的內存拷貝
- 生成一條重做日誌並寫入redo log buffer,記錄的是數據被修改後的值
- 當事務commit時,將redo log buffer中的內容刷新到 redo log file,對 redo log file採用追加寫(順序寫)的方式
- 定期將內存中修改的數據刷新到磁盤中
從上圖中可以看出,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