文章目錄
- 1. Buffer Pool 緩沖池
- 2. redo log (重做日志)
- redo log 的作用:
- 為什么需要 redo log buffer?
- 什么時候刷盤呢?
- 3. 總結一下 redo log 和 Buffer Pool 在更新數據時的協同工作
- 關鍵組件關系圖
- 刷盤完成后
1. Buffer Pool 緩沖池
首先,需要理解一個核心問題:數據庫的更新操作,直接寫到磁盤是非常慢的。 磁盤是機械設備,讀寫速度遠低于內存。如果每次更新都直接寫盤,數據庫的性能會非常差。
為了解決這個問題,數據庫引入了內存緩存的概念,也就是圖中的 Buffer Pool (緩沖池)。
可以把 Buffer Pool 想象成一個高速緩存區,它存儲了數據庫中經常訪問的數據頁(數據在磁盤上是以“頁”為單位存儲的)。
- 讀取數據時: 如果要讀取的數據頁已經在 Buffer Pool 中,就直接從內存讀取,速度非常快。如果不在,就需要從磁盤加載到 Buffer Pool 中,然后再從 Buffer Pool 中讀取。
- 更新數據時: 數據庫并不會直接將更新后的數據寫回磁盤,而是先將更新操作應用到 Buffer Pool 中的數據頁上。
2. redo log (重做日志)
現在問題來了,如果數據只更新到了 Buffer Pool,還沒有寫回磁盤,這個時候數據庫突然崩潰了,怎么辦?內存中的數據就會丟失,導致數據不一致。
這就是 redo log (重做日志) 的作用。
可以把 redo log 想象成一個操作日志本,它記錄了數據庫的所有更新操作。
- 當你執行一個更新操作時,InnoDB 存儲引擎會先將這個更新操作記錄到 redo log buffer (重做日志緩存) 中。
- 然后,再將更新應用到 Buffer Pool 中的數據頁。
這個過程非常重要:先寫日志,再更新內存。 這就是所謂的 WAL (Write-Ahead Logging,先寫日志) 技術。
redo log 的作用:
redo log 的主要作用是 保證事務的持久性。即使數據庫崩潰,只要 redo log 中的數據沒有丟失,就可以通過回放 redo log 來恢復崩潰前的數據狀態。
我們結合圖來看整個流程:
[應用程序] ││ UPDATE user SET balance=200 WHERE id=1▼
[InnoDB引擎]├── 1. 從磁盤加載數據頁到 → [Buffer Pool](內存緩沖區)├── 2. 修改Buffer Pool中的數據(產生臟頁)├── 3. 記錄物理修改到 → [redo log buffer](內存)└── 4. 提交事務時將redo log刷盤 → [ib_logfile](磁盤)│└── 后臺線程異步將臟頁刷回磁盤數據文件
- 磁盤加載數據放入緩沖池 :當你需要讀取或修改某個數據時,如果它不在 Buffer Pool 中,會先從磁盤加載到 Buffer Pool 中。
- 直接更新緩存數據 :更新操作會直接作用于 Buffer Pool 中的數據頁。
- 記錄更新信息:同時,這個更新操作的信息會被記錄到
redo log buffer
中。 - 清空
redo log buffer
刷盤到 redo 日志中:redo log buffer
中的內容會定期或在特定時機(比如事務提交時)被刷寫到磁盤上的redo log
文件中。
為什么需要 redo log buffer?
redo log buffer
就像一個臨時的緩沖區,用于存放最近的 redo log 記錄。先寫到 buffer 中比直接寫到磁盤更快。當 buffer 滿了或者滿足其他條件時,才會將 buffer 中的內容批量刷寫到磁盤,減少了磁盤 I/O 的次數。
什么時候刷盤呢?
redo log buffer 刷盤到磁盤的時機有很多種,包括:
- 事務提交時: 這是最常見的刷盤時機,保證了事務的持久性。
- 當 redo log buffer 空間不足時: 如果 redo log buffer 快滿了,會強制刷盤。
- 后臺線程定時刷盤: InnoDB 有后臺線程會定期將 redo log buffer 中的內容刷盤。
- 正常關閉數據庫時: 關閉數據庫之前,會把 redo log buffer 中的內容刷盤。
3. 總結一下 redo log 和 Buffer Pool 在更新數據時的協同工作
- 更新操作先寫到
redo log buffer
。 - 更新操作應用到 Buffer Pool 中的數據頁。
- redo log buffer 中的內容在合適的時機刷寫到磁盤上的
redo log
文件。 - Buffer Pool 中的臟頁(被修改過但還沒寫回磁盤的數據頁)會在合適的時機(比如后臺線程、Buffer Pool 空間不足等)刷寫到磁盤上的數據文件。
通過這種方式,數據庫可以在保證數據持久性的同時,提高更新操作的性能,因為大部分更新操作都先在內存中完成。即使發生崩潰,也可以通過 redo log 來恢復數據。
關鍵組件關系圖
+-------------------+ 1.記錄操作 +-------------------+
| redo log buffer | <-------------- | 事務更新請求 |
| (內存日志緩存) | | |
+-------------------+ +--------+----------+| 2.刷日志(保證持久性) | 3.修改內存數據V V
+-------------------+ +----------------------+
| 磁盤 redo log文件 | | Buffer Pool |
| (安全存儲的操作記錄)| | (內存數據頁) |
+-------------------+ | |^ | 4.標記為臟頁 || +----------------------+| || 5.推進檢查點(釋放日志空間) | 6.觸發刷盤條件|----------------------------------------+V V
+-------------------+ +----------------------+
| 磁盤數據文件 | <------------- | 后臺線程刷臟頁 |
| (最終持久化數據) | 7.覆蓋寫數據 | (將臟頁內容寫入磁盤) |
+-------------------+ +----------------------+
刷盤完成后
- 臟頁變干凈:Buffer Pool 中該頁標記為「非臟頁」(與磁盤一致)
- 推進檢查點 (Checkpoint)
- 系統記錄:「此臟頁數據已落盤,其對應的 redo log 記錄可被覆蓋」
- 磁盤 redo log 文件:釋放舊日志空間(循環復用)
磁盤一致)
- 推進檢查點 (Checkpoint)
- 系統記錄:「此臟頁數據已落盤,其對應的 redo log 記錄可被覆蓋」
- 磁盤 redo log 文件:釋放舊日志空間(循環復用)