MySQL事務日誌
MySQL事務日誌
我們知道,MySQL事務有4個特性:隔離性、永續性、原子性、一致性。事務的隔離性是由鎖來實現的。原子性、一致性、永續性通過資料庫的redo log和undo log來完成。redo log稱為重做日誌,用來保證事務的原子性和永續性。Undo log用來保證事務的一致性。事務要保證 ACID 的完整性必須依靠事務日誌做跟蹤。
至關重要的三種log:
binlog 二進位制日誌
redo log 重做日誌
undo log 回滾日誌
一、redo log
重做日誌用來實現事務的永續性,即事務ACID中的D。
1、作用
記錄的是尚未完成的操作,資料庫崩潰則用其重做
2、組成
其由兩部分組成:
1)記憶體中的重做日誌緩衝(redo log buffer),其是易失的
2)重做日誌檔案(redo log file),其是持久的
3、如何保證事務的永續性?
通過Force Log at Commit 機制,即當事務commit提交時,innodb引擎先將 redo log buffer 寫入到 redo log file 進行持久化,待事務的commit操作完成時才算完成。這種做法也被稱為 Write-Ahead Log(預先日誌持久化),在持久化一個數據頁之前,先將記憶體中相應的日誌頁持久化。
4、工作流程
1)事務開啟時,事務中的操作,都會先寫入儲存引擎的日誌緩衝。
2)在事務提交之前,緩衝的日誌都需要提前重新整理到磁碟上持久化,這就常說的“日誌先行”(Write- Ahead-Logging)。
3)當事務提交之後,在Buffer Pool 中對映的資料檔案才會慢慢重新整理到磁碟。
4) 此時如果資料庫崩潰或者宕機,那麼當系統重啟進行恢復時,就可以根據 redo log 中記錄的日誌,把資料庫恢復到崩潰前的一個狀態。
5)未完成的事務,可以繼續提交,也可以選擇回滾,這基於恢復的策略而定。
說明:在系統啟動的時候,就已經為 redo log 分配了一塊連續的儲存空間,以順序追加的方式記錄 Redo Log,通過順序 IO 來改善效能。所有的事務共享 redo log 的儲存空間,它們的 Redo Log 按語句的執行順序,依次交替的記錄在一起。
5、持久化策略
為了確保每次日誌都能寫入到事務日誌檔案中,在每次將 log buffer 中的日誌寫入日誌檔案的過程中都會呼叫一次作業系統的 fsync 操作(即 fsync() 系統呼叫)。
6、重做日誌檔案寫入流程
先寫重做日誌檔案1,當檔案1被順序寫滿時,會切換到重做日誌檔案2,再當重做日誌檔案2也被寫滿時,會再切換到重做日誌檔案1中,依次迴圈; 所以說重做日誌檔案是 迴圈覆蓋寫入的 。
因為重做日誌是迴圈覆蓋寫入的,所以不能使用其進行整個資料庫的資料恢復,它只能保證資料庫宕機時的事務的完整性資料;如果想要恢復全部資料的話,只能使用 binlog 二進位制日誌(歸檔日誌)進行恢復。
注意:大家可以手動修改重做日誌檔案組下的檔案數量,並可以指定每個重做日誌檔案的大小,通過下面的引數:
innodb_log_file_size 指定重做日誌檔案的大小
innodb_log_files_in_group 重做日誌檔案組下的檔案數量
二、undo log
undo log有兩個作用:提供回滾和多個行版本控制(MVCC)。
undo log和redo log記錄物理日誌不一樣,它是邏輯日誌。因此只是將資料庫邏輯得恢復到原來的樣子。。可以認為當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。
undo log 是邏輯日誌,可以理解為:
當 delete 一條記錄時,undo log 中會記錄一條對應的 Insert 記錄
當 insert 一條記錄時,undo log 中會記錄一條對應的 delete 記錄
當 update 一條記錄時,它記錄一條對應相反的 update 記錄
舉一個例子:
假設有 2 個數值,分別為 A=1 和 B=2, 然後將 A 修改為 3, B 修改為 4。
下面是事務的整個工作流程:
start transaction
記錄 A=1 到 undo log;
Update A=3
記錄 A=3 到 redo log
記錄 B=2 到 undo log
Update B=4
記錄 B=4 到 redo log
將 redo log 重新整理到磁碟
Commit
在 1-8 步驟的任意一步系統宕機,事務未提交,該事務就不會對磁碟上的資料做任何影響。
如果在 8-9 之間宕機,恢復之後可以選擇回滾,也可以選擇繼續完成事務提交,因為此時 redo log 已經持久化。
若在 9 之後系統巖機,記憶體對映中變更的資料還來不及刷回磁碟,那麼系統恢復之後,可以根據 redo log 把資料刷回磁碟
所以,redo log 其實保障的是事務的永續性和原子性,而 undo log,則保障了事務的一致性。
三、binlog
binlog 二進位制日誌(歸檔日誌),這個日誌是由MySql的 server層進行維護的;不管當前MySql使用的是什麼儲存引擎,binlog歸檔日誌都是支援的.
1、作用
用於複製,在主從複製中,從庫利用主庫上的binlog進行重播,實現主從同步。
資料恢復,用於資料庫的基於時間點的還原。
2、binLog的格式
binlog 共有三種儲存格式: row, statement 和 混合模式。
1)row: 記錄哪行資料被修改的
資料記錄方式比較簡單,但是可能會產生大量的資料廢棄日誌(如 更新一個全表)。
2)statement: 記錄修改資料的 SQL ,不記錄修改的資料
記錄資料的過程,日誌量比較小,IO 讀寫少。缺點是 有些函式並不支援,為了保證能夠一致性,必須還需要有一些上下文的資訊。
3)混合模式: 是以上兩種模式的混合使用,MySQL 會根據執行的每一條具體的 sql 語句來區分對待記錄的日誌形式。
一般的語句修改使用 statment 格式儲存 binlog ,如一些函式,statement 無法完成主從複製的操作,則採用 row 格式儲存 binlog。
3、與 redo 日誌的區別
1)redo 是 Innodb 獨有的,binlog 是所有引擎都可以使用的
2)redo 是物理日誌,記錄的是在某個資料頁上做了什麼修改,binlog 是邏輯日誌,記錄的是這個語句的原始邏輯。
3)redo 是迴圈寫的,空間會用完,binlog 是可以追加寫的,不會覆蓋之前的日誌資訊。
4)Binlog 中會記錄所有的邏輯,並且採用追加寫的方式
注意:
binlog二進位制日誌檔案在預設情況下並沒有啟動,需要手動進行開啟的。根據MySql的官網手冊瞭解到,開啟此日誌會使效能下降1%左右,這個損失大體上是可以接受的。
參考連結:
https://cloud.tencent.com/developer/article/1780893