MySQL的Undo-log與Redo-log的實作機制
本文将詳細介紹什麼是
Undo Log
、
Redo Log
。
MySQL預設的Innodb在REPEATABLE READ隔離級别下,是如何通過
MVCC
+
Undo Log
,解決幻讀的。
1. Undo Log是什麼
1.1 簡介
Undo Log
:
undo
意為取消,以撤銷操作為目的,傳回指定某個狀态的操作
undo log
指事務開始之前,在操作任何資料之前,首先将需操作的資料備份到一個地方 (
Undo Log
)
UndoLog是為了實作事務的原子性而出現的産物
Undo Log
實作事務原子性:
事務處理過程中如果出現了錯誤或者使用者執行了
ROLLBACK
語句,MySQL可以利用
Undo Log
中的備份将資料恢複到事務開始之前的狀态
Undo Log
在MySQL Innodb存儲引擎中用來實作多版本并發控制
Undo log
實作多版本并發控制:
事務未送出之前,Undo儲存了未送出之前的版本資料,Undo 中的資料可作為資料舊版本快照供其他并發事務進行快照讀
1.1 案例
如下圖
事務A 執行
update
之前,備份數舊資料 --> Undo buffer -->落地 Undo Log
事務B 此時查詢的是Undo buffer中的内容(相當于讀取的是快照,實作多版本并發控制)
事務A 若因意外rollback,會從Undo buffer中資料恢複(實作事務原子性)

1.2 目前讀、快照讀
快照讀:
SQL讀取的資料是快照版本,也就是曆史版本,普通的SELECT就是快照讀Innodb快照讀,資料的讀取将由 cache(原本資料) + undo(事務修改過的資料) 兩部分組成
目前讀:
SQL讀取的資料是最新版本。通過鎖機制來保證讀取的資料無法通過其他事務進行修改
UPDATE
、
DELETE
、
INSERT
、
SELECT … LOCK IN SHARE MODE
、
SELECT … FOR UPDATE
都是目前讀
2. Redo Log是什麼
2.1 簡介
Redo Log
:
Redo
,顧名思義就是重做。以恢複操作為目的,重制操作;
Redo log
指事務中操作的任何資料,将最新的資料備份到一個地方 (
Redo Log
)
Redo log的持久:
不是随着事務的送出才寫入的,而是在事務的執行過程中,便開始寫入redo 中。具體的落盤政策可以進行配置
RedoLog是為了實作事務的持久性而出現的産物
Redo Log
實作事務持久性:
防止在發生故障的時間點,尚有髒頁未寫入磁盤,在重新開機MySQL服務的時候,根據
Redo Log
進行重做,進而達到事務的未入磁盤資料進行持久化這一特性。
2.2 Redo Log的落盤配置
指定Redo log 記錄在{datadir}/ib_logfile1&ib_logfile2 可通過
innodb_log_group_home_dir
配置指定目錄存儲
mysql> show variables like "innodb_log_group_home_dir";
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| innodb_log_group_home_dir | ./ |
+---------------------------+-------+
1 row in set (0.01 sec)
mysql>
一旦事務成功送出且資料持久化落盤之後,此時Redo log中的對應事務資料記錄就失去了意義,是以Redo log的寫入是日志檔案循環寫入的
指定Redo log日志檔案組中的數量
innodb_log_files_in_group
預設為2
指定Redo log每一個日志檔案最大存儲量
innodb_log_file_size
預設48M
指定Redo log在cache/buffer中的buffer池大小
innodb_log_buffer_size
預設16M
Redo buffer 持久化Redo log的政策
Innodb_flush_log_at_trx_commit
:
mysql> show variables like "Innodb_flush_log_at_trx_commit";
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 0 |
+--------------------------------+-------+
1 row in set (0.01 sec)
mysql>
- 取值 0 每秒送出 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丢失一秒内的事務資料]
- 取值 1 預設值,每次事務送出執行Redo buffer --> Redo log OS cache --> flush cache to disk[最安全,性能最差的方式]
- 取值 2 每次事務送出執行Redo buffer --> Redo log OS cache 再每一秒執行 --> flush cache to disk操作