預寫式日誌 WAL 簡介

【導讀】WAL 是一種什麼操作?在數據庫和消息隊列中爲什麼用到這種技術?本文對 WAL 做了詳細介紹。

引言

Write Ahead Logging,簡稱 WAL,也被翻譯成預寫式日誌,是數據庫技術中實現事務日誌 (Transaction Journal) 的一種標準方法,可以實現單機事務的原子性,同時可以提高數據庫的寫入效率。

思考如下場景,如何確保原子性:寫操作修改數據庫中 a 和 b 的值,二者是一個事務,需要把 a 和 b 的最新值持久化到磁盤,假如保存完 a 的值,系統宕機了,重新啓動後,a 的值已經寫入,但 b 待寫入的值已經丟失,如何發現事務沒有完成呢?如何保證事務的原子性呢?

可以爲事務加鎖,也爲事務增加標誌位,修改完磁盤數據後,標誌位設置事務爲完成,事務狀態保存在磁盤中,假使保存事務狀態的過程中宕機了,就把事務回滾掉。實現 REDO 和 UNDO,就能實現原子性。

數據庫中針對 Crash 和 Recovery 的解決方案是 WAL。

原理

WAL 的核心思想是先寫日誌再寫數據文件,修改數據文件必須發生在修改操作記錄在日誌文件之後。

本文的日誌指事務的操作日誌,本文提到的日誌都是指事務日誌,不再特殊聲明。

我們看 WAL 怎麼解決宕機和恢復的問題:

如此,保證了數據的恢復和事務的原子性。

上面提到的都是寫操作,看一下使用 WAL 時的讀操作。WAL 中可能包含了未寫入到數據庫文件中的最新值,如果讀最新值就需要從 WAL 中讀取,如果 WAL 中未讀到,從數據庫讀到的就是最新的數據。

檢查點:寫入到 WAL 文件中的操作記錄並不一定會立刻應用到數據庫文件上,這個過程是異步的,設計檢查點來記錄已經被應用到數據庫文件上的操作序號,檢查點後面的操作記錄等待被應用到數據庫文件上。

優點

WAL 的作用是解決宕機和恢復的問題,同時也有其他優點:

  1. 提高寫數據的性能
  1. 保證事務原子性

  2. 保證事務一致性

  3. 併發讀寫,比如 SQLite 中,讀寫、讀讀都是可以並行的,比如讀時需要找到 WAL 某個值最後寫入的位置,就可以從該位置讀數據,而寫操作是在 WAL 文件後 Append,二者並行。但寫寫不能並行,因爲 2 次寫操作都要向 WAL 文件 Append 數據,無法同時進行。

  4. WAL 文件中記錄了數據的歷史版本,因此可以讀取歷史版本的值,甚至把狀態回滾到某個歷史版本。

缺點

SQLite 提到了 WAL 的幾項缺點:

  1. WAL 需要 VFS 的支持。

  2. 所有使用數據庫的進程必須在同一個機器上,以爲 WAL 是單機的。

  3. 多讀少寫的場景 WAL 比 rollback-journal 類型要慢 1%~2%。

使用場景

WAL 幾乎是數據存儲 (數據庫只是數據存儲的一個類別,只不過這個類別很大) 的標配:

轉自:大彬

lessisbetter.site/2020/01/02/wal-introduction/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/L6Fjpbm3rZXs3X1mrui5eQ