MySQL學習筆記
redo log
1. 什麼是WAL(Write-Ahead Logging)
1.1 百度百科:
預寫日誌系統
數據庫中一種高效的日誌算法,對於非內存數據庫而言,磁盤I/O操作是數據庫效率的一大瓶頸。
在相同的數據量下,採用WAL日誌的數據庫系統在事務提交時,磁盤寫操作只有傳統的回滾日誌的一半左右,大大提高了數據庫磁盤I/O操作的效率,從而提高了數據庫的性能
(說了跟沒說一樣)
1.2 大白話說就是:
- 所有寫操作,先寫到日誌中,再去修改具體的數據
舉個例子:
- 設磁盤
a扇區
存了一個數據b=1
,現在我想改成b=2
- 按照WAL的思路,我不會直接修改
a扇區
的內容 - 而是將修改
b=2
這個操作,保存在一個日誌文件中,等系統空閒的時候,再去修改a扇區
2. 什麼是redo log
redo log
就是MySQL的InnoDB引擎使用的WAL機制的具體實現
MySQL是這麼做的:
- 當有一條記錄需要更新的時候
- InnoDB 引擎就會先把記錄寫到 redo log 裏面,並更新內存,這個時候更新就算完成了。(redo log 記錄下數據塊的改動)
- 同時,InnoDB 引擎會在適當的時候,將這個操作記錄更新到磁盤裏面,而這個更新往往是在系統比較空閒的時候做
3. 爲什麼要用redo log
3.1. 提高寫效率
- redo log 只保存沒有刷新到磁盤上的操作內容, 寫的是一個連續的硬盤空間, 硬盤的順序讀寫, 要比4k隨機讀寫快太多了
找個表格看看(表格表示的是數量級上的區別,不是具體的讀寫速度)
延遲 | 順序讀寫速度 | 4k隨機讀寫速度 | |
---|---|---|---|
機械硬盤 | 2500000ns | 100MB/s | 1MB/s |
固態硬盤 | 15000ns | 1000MB/s | 10MB/s |
內存 | 100ns | 10000MB/s | 500MB/s |
L3 cache | 1ns | >100000MB/s | >100000MB/s |
(1,000,000納秒=1毫秒)
3.2. 保證crash-safe
- 即使數據庫發生異常重啓,之前提交的記錄都不會丟失
- 當數據庫重啓的時候,可以根據redo log恢復之前提交的事務
4. redo log 是怎麼保存數據的?
- InnoDB 的 redo log 是固定大小的
- 比如可以配置爲一組 4 個文件,每個文件的大小是 1GB
- 那麼這塊硬盤空間總共就可以記錄 4GB 的操作。
- 從頭開始寫,寫到末尾就又回到開頭循環寫
4.1 保存形式
- 物理格式的日誌,記錄的是物理數據頁面的修改的信息,其redo log是順序寫入redo log file的物理文件中去的。
redo log
是以循環寫的方式來在日誌文件中寫入的write pos
是當前記錄的位置,一邊寫一邊後移。checkpoint
是當前要擦除的位置,也是往後推移並且循環的,擦除記錄前要把記錄更新到數據文件。write pos
和checkpoint
之間的是redo log
上還空着的部分,可以用來記錄新的操作。- 如果
write pos
追上checkpoint
,表示“粉板”滿了,這時候不能再執行新的更新,得停下來先擦掉一些記錄,把checkpoint
推進一下。
redo log 一般保存在日誌文件 ib_logfile0 和 ib_logfile1 這種文件中
修改 ib_logfile 的 個數 和 大小 以及 存放路徑:
可以通過參數innodb_log_files_in_group來改變文件個數,這個參數的默認值是2;
可以通過參數innodb_log_file_size來指定每個redo日誌的大小;
可以通過參數innodb_log_group_home_dir指定redo日誌所在的目錄。
4.2 如何保存數據到redo log
有這些場景會將redo log buffer
寫入 redo log
:
- 當事務commit的時候,
redo log buffer
的內容會被寫入redo log
- InnoDB 有一個後臺線程,每隔 1 秒,就會把
redo log buffer
中的日誌,調用 write 寫到文件系統的page cache
,然後調用fsync
持久化到磁盤。 redo log buffer
佔用的空間即將達到innodb_log_buffer_size
一半的時候,後臺線程會主動寫盤- 並行的事務提交的時候,順帶將這個事務的 redo log buffer 持久化到磁盤
- 當內存數據頁跟磁盤數據頁內容不一致的時候,我們稱這個內存頁爲“髒頁”。內存數據寫入到磁盤後,內存和磁盤上的數據頁的內容就一致了,稱爲“乾淨頁”。