Chapter 11. 預寫式日誌(Write-Ahead Logging (WAL))

Table of Contents
11.1. 一般性描述
11.1.1. WAL 中獲取的直接好處
11.1.2. 更多好處
11.2. 實現
11.3. WAL 配置

作者: Vadim Mikheev 和 Oliver Elphick

11.1. 一般性描述

預寫式日誌WAL) 是一種實現事務日誌的標準方法.有關它的詳細描述可以在 大多數(如果不是全部的話)有關事務處理的書中找到. 簡而言之,WAL 的中心思想是對資料文件 的修改(它們是表和索引的載體)必須是只能發生在這些修改已經 記錄了日誌之後 -- 也就是說,在日誌記錄衝刷到永久儲存器之後. 如果我們遵循這個過程,那麼我們就不需要在每次事務提交的時候 都把資料頁衝刷到硬碟,因為我們知道在出現崩潰的情況下, 我們可以用日誌來恢復資料庫:任何尚未附加到資料頁的記錄 都將先從日誌記錄中重做(這叫向前滾動恢復,也叫做 REDO) 然後那些未提交的事務做的修改將被從資料頁中刪除 (這叫向後滾動恢復 - UNDO).

11.1.1. 從 WAL 中獲取的直接好處

使用 WAL 的第一個明顯的好處就是顯著地 減少了硬碟寫的次數.因為在日誌提交的時候只有日誌文件需要衝刷到硬碟﹔ 在多使用者環境裡,許多事務的提交可以用日誌文件的一次 fsync() 來完成.而且,日誌文件是順序寫的, 因此同步日誌的開銷要遠比同步資料頁的開銷要小.

另外一個好處就是資料頁的完整性.實際情況是,在 WAL 之前,PostgreSQL 從來不能保証 在崩潰的情況下資料頁的完整性.在 WAL之前,在寫的過程中的任何崩潰都可能導致:

  1. 索引記錄指向一個不存在的表的行

  2. 索引記錄在分裂操作中丟失

  3. 完全崩潰了的表和索引頁的內容,因為資料頁只寫了一部分

索引的問題(問題 1 和 2)可能已經通過額外的 fsync() 調用修補好了,但是如果沒有 WAL,那麼沒有很明顯的 處理第三種情況的方法﹔WAL 在日誌裡保存整個 資料頁的內容 -- 如果那些內容在崩潰後的恢復中需要確保資料頁的完整性的話.

11.1.2. 更多好處

UNDO 操作還沒有實現。 這就意味著由退出的事務做的修改將仍然占據硬碟空間, 因此我們仍然需要一個永久的 pg_clog 文件 保存事務的狀態,因為我們不能回收事務標識符.一旦實現了 UNDO, 那麼 pg_clog 就不再要求是永久的了﹔ 我們就有可能在關閉的時候刪除 pg_clog. (不過,這方面的緊迫性已經隨著我們對 pg_clog 採取分段儲存的方法而降低了 --- 我們不再需要永久保留 pg_clog 記錄.)

有了 UNDO,我們還可能實現 savepoints, 這樣就允許非法事務操作的部分回卷(因為誤敲了命令導致的分析器錯誤, 插入了重復的主鍵/唯一鍵字等等)同時還能夠繼續或提交該事務在 發生錯誤之前的合法操作.目前,任何錯誤都將使整個事務成為非法並且 要求事務退出.

WAL 還提供了資料庫線上備份和恢復 (backup and restore (BAR))的新方法. 要使用這個方法,我們可能要經常性地把資料文件保存到另外一個硬碟, 磁帶或者另外一台主機並且還要備份 WAL 日誌文件. 那麼資料庫文件拷貝和日誌歸檔文件就可以用於象災難恢復中那樣 恢復資料.每次做完新資料庫文件以後,這個老的日誌文件就可以刪除了. 實現這個設施可能需要記錄資料文件和索引建立和刪除的日誌﹔ 同時還需要開發一種方法來拷貝資料文件(操作系統拷貝命令是不合適的).

認識這些事情的好處的一個困難是它們要求在相當可觀的時間段內 保存 WAL 日誌(也就是說,如果需要事務的 UNDO, 那麼和可能的最長的事務的時間一樣長).目前的 WAL 格式的體積相當大,因為它包括多個硬碟頁的鏡像. 目前這還不是一個嚴重的問題,因為這些日誌只需要保留一到兩個 檢查點的時間間隔﹔但是為了實現這些東西,以後我們可能需要某種壓縮的 WAL 格式.