MySQL實現事務的提交和回滾

菜鳥的突變發表於2020-12-02

什麼是事務?
事務是資料庫中一系列的訪問和更新組成的邏輯執行單元,事務的邏輯單元中可以是一條SQL語句,也可以是一段SQL邏輯,這段邏輯要麼全部執行成功,要麼全部執行失敗。
也就是說事務就是用來保證一系列操作的原子性,
資料庫為了保證事務的原子性和永續性,引入了redo log 和 undo log
redo log
redo log是重做日誌,是物理日誌,記錄的是物理資料頁的修改,它用來恢復叫後的物理資料頁,
在這裡插入圖片描述
redo log 分為兩部分:

  1. 記憶體中的redo log buffer是日誌緩衝區,這部分資料容易丟失

  2. 磁碟中的redo log file是日誌檔案,這部分資料已經持久化磁碟,不容易丟失
    SQL運算元據庫之前,會先記錄重做日誌,為了保證效率會先寫到日誌緩衝區中(redo log buffer),再通過緩衝區寫到磁碟檔案中進行持久化,存在緩衝區就說明資料不是實時的寫到redo log file 中,在這時伺服器突然斷電,那麼redo log會丟失資料。
    在MySQL中可以自己控制 redo log buffer 重新整理到log file中的頻率,通過innodb_flush_log_trx_commit引數可以設定事務提交的log buffer 如何儲存到log file中,innodb_flush_log_trx_commit引數有三個值(0,1,2)

  3. 為1表示事務每次提交都會將log buffer寫入到os buffer,並呼叫作業系統的fsync()方法將日誌寫入log file,這種方式的好處是就算MySQL崩潰也不會丟資料,redo log file儲存了所有已提交事務的日誌,MySQL重新啟動後會通過redo log file進行恢復。但這種方式每次提交事務都會寫入磁碟,IO效能較差

  4. 為0表示事務提交時不會將log buffer寫入到os buffer中,而是每秒寫入os buffer然後呼叫fsync()方法將日誌寫入log file,這種方式在MySQL系統崩潰時會丟失大約1秒鐘的資料

  5. 為2表示事務每次提交僅將log buffer寫入到os buffer中,然後每秒呼叫fsync()方法將日誌寫入log file,這種方式在MySQL崩潰時也會丟失大約1秒鐘的資料
    undo log
    undo log 是回滾日誌,用來回滾行記錄到一個版本,undo log一般是邏輯日誌,根據行的資料變化進行記錄
    undo log 跟redo log一樣也是在SQL運算元據之前記錄的,也就是SQL操作先記錄日誌,在進行運算元據
    在這裡插入圖片描述
    如上圖所示,SQL操作之前會先記錄redo log、undo log到日誌緩衝區,日誌緩衝區的資料會記錄到os buffer中,再通過呼叫fsync()方法將日誌記錄到log file中

undo log記錄的是邏輯日誌,可以簡單的理解為:當insert一條記錄時,undo log會記錄一條對應的delete語句;當update一條語句時,undo log記錄的是一條與之操作相反的語句

當事務需要回滾時,可以從undo log中找到相應的內容進行回滾操作,回滾後資料恢復到操作之前的狀態

undo日誌還有一個用途就是用來控制資料的多版本(MVCC),在《InnoDB儲存引擎中的鎖》一文中講到MVCC是通過讀取undo日誌中資料的快照來進行多版本控制的

undo log是採用段(segment)的方式來記錄的,每個undo操作在記錄的時候佔用一個undo log segment。

另外,undo log也會產生redo log,因為undo log也要實現永續性保護

總結一下

MySQL中如何實現事務提交和回滾的?

  1. 為了保證資料的持久化,資料庫在執行SQL運算元據之前會先記錄redo log和undo log
  2. redo log 是重做日誌,通常物理日誌,記錄的是物理資料頁的修改,它用來恢復提交後的物理資料頁
  3. undo log是回滾日誌,用來會滾滾行記錄到一個版本,undo log一般是邏輯日誌,根據行的資料變化進行記錄
  4. redo、undo log 都是寫先寫到日誌緩衝區,在通過緩衝區寫到磁碟日誌檔案中進行持久化儲存
  5. undo日誌還有一個用途就是用來控制資料的多版本

簡單的理解:
redo log是用來恢復資料的,用於保障已提交事務的持久化
undo log是用來回滾事務的,使用者保障未提交事務的原子性

相關文章