MySQL事务日志
MySQL事務日志
我們知道,MySQL事務有4個特性:隔離性、持久性、原子性、一致性。事務的隔離性是由鎖來實現的。原子性、一致性、持久性通過數據庫的redo log和undo log來完成。redo log稱為重做日志,用來保證事務的原子性和持久性。undo log用來保證事務的一致性。事務要保證 ACID 的完整性必須依靠事務日志做跟蹤。
至關重要的三種日志:
binlog 二進制日志
redo log 重做日志
undo log 回滾日志
一、redo log
重做日志用來實現事務的持久性,即事務ACID中的D。
1、作用
redo通常是物理日志,記錄的是頁的物理修改操作,數據庫崩潰則用其重做。
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 操作。
6、重做日志文件寫入流程
先寫重做日志文件1,當文件1被順序寫滿時,會切換到重做日志文件2,再當重做日志文件2也被寫滿時,會再切換到重做日志文件1中,依次循環; 所以說重做日志文件是循環覆蓋寫入的 。
因為重做日志是循環覆蓋寫入的,所以不能使用其進行整個數據庫的數據恢復,它只能保證數據庫宕機時的事務的完整性數據;如果想要恢復全部數據的話,只能使用 binlog 二進制日志(歸檔日志)進行恢復。
注意:大家可以手動修改重做日志文件組下的文件數量,并可以指定每個重做日志文件的大小,通過下面的參數:
1)innodb_log_file_size 指定重做日志文件的大小
2)innodb_log_files_in_group 重做日志文件組下的文件數量
二、undo log
1、作用
undo log有兩個作用:提供回滾和多個行版本控制(MVCC)。
2、工作流程
1)邏輯日志
undo log 和 redo log 記錄物理日志不一樣,它是邏輯日志,根據每行記錄進行記錄,因此只是將數據庫邏輯得恢復到原來的樣子。
undo log 是邏輯日志,可以理解為:
當 delete 一條記錄時,undo log 中會記錄一條對應的 Insert 記錄
當 insert 一條記錄時,undo log 中會記錄一條對應的 delete 記錄
當 update 一條記錄時,它記錄一條對應相反的 update 記錄
2)舉例
假設有 2 個數值,分別為 A=1 和 B=2, 然后將 A 修改為 3, B 修改為 4。
下面是事務的整個工作流程:
步驟1. start transaction
步驟2. 記錄 A=1 到 undo log;
步驟3. Update A=3
步驟4. 記錄 A=3 到 redo log
步驟5. 記錄 B=2 到 undo log
步驟6. Update B=4
步驟7. 記錄 B=4 到 redo log
步驟8. 將 redo log 刷新到磁盤
步驟9. Commit
在 1-8 步驟的任意一步系統宕機,事務未提交,該事務就不會對磁盤上的數據做任何影響。
如果在 8-9 之間宕機,恢復之后可以選擇回滾,也可以選擇繼續完成事務提交,因為此時 redo log 已經持久化。
若在 9 之后系統巖機,內存映射中變更的數據還來不及刷回磁盤,那么系統恢復之后,可以根據 redo log 把數據刷回磁盤
所以,redo log 其實保障的是事務的持久性和原子性,而 undo log,則保障了事務的一致性。
三、binlog
binlog 二進制日志(歸檔日志),這個日志是由MySql的 server層進行維護的;不管當前MySql使用的是什么存儲引擎,binlog歸檔日志都是支持的.
1、作用
1)用于復制,在主從復制中,從庫利用主庫上的binlog進行重播,實現主從同步。
2)數據恢復,用于數據庫的基于時間點的還原。
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
https://segmentfault.com/a/1190000039715378
總結
- 上一篇: 使用Remmina远程登录Ubuntu系
- 下一篇: 网络处理2-异步POST请求和同步请求