| PostgreSQL 8.0.0 中文文件(轉譯自 PostgreSQL 中國 製作的簡體中文版本) | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 25. 預寫式日誌(Write-Ahead Logging (WAL)) | Fast Forward | Next |
有幾個與 WAL 相關的參數會影響資料庫性能。 本節討論它們的使用。參閱 Section 16.4 獲取有關伺服器配置參數的一般訊息。
檢查點(Checkpoints) 是交易序列中的點, 我們保證在該點之前的所有日誌訊息都更新到資料文件中去了。 在檢查點時,所有髒資料頁都沖刷到磁盤並且向日誌文件中寫入一條特殊的檢查點記錄。 結果是,在發生崩潰的時候,恢復器就知道應該從日誌中的哪個點(稱做 redo 記錄)開始做 REDO 操作, 因為在該記錄前的對資料文件的任何修改都已經在磁盤上了。 在完成檢查點處理之後,任何在 redo 記錄之前寫的日誌段都不再需要, 因此可以循環使用或者刪除。(在進行 WAL 歸檔的時候, 這些日誌在循環利用或者刪除之前必須先歸檔。)
伺服器的後端寫進程將每隔這段時間就自動執行一個檢查點。 每隔 checkpoint_segments 個日誌段就建立一個檢查點, 或者每隔 checkpoint_timeout 秒建立一個。 以先到為準。預設設置分別是 3 個段和 300 秒。 我們也可以用 SQL 命令 CHECKPOINT 強制一個檢查點。
減少 checkpoint_segments 和/或 checkpoint_timeout 會令檢查點更頻繁一些。 這樣就允許更快的崩潰後恢復(因為需要重做的工作更少)。不過, 我們必須在這個目的和更頻繁地沖刷髒資料頁所帶來的額外開銷之間取得平衡。 另外,為了保證資料頁的一致性,在每個檢查點之後的第一次資料頁的變化會導致對整個頁面內容的日誌記錄。 因此,檢查點時間間隔短了會導致輸出到 WAL 日誌中的資料的增加,會抵銷一部分縮短間隔的目標, 並且怎麼著都會產生更多的磁盤 I/O。
檢查點開銷相當高,首先是因為它需要寫出所有目前髒的緩衝區,其實是因為他們導致上面討論的額外的後繼 WAL 流量。 因此把檢查點參數設置得足夠高,讓檢查點發生的頻率降低是明智的。要對您的檢查點參數的一個簡單自檢,可以設置 checkpoint_warning 參數。如果檢查點發生的間隔接近 checkpoint_warning 秒, 那麼將向伺服器日誌輸出一條消息,建議您增加 checkpoint_segments 的數值。 偶爾出現的這樣的警告並不會導致警告,但是如果它出現得太頻繁,那麼就應該增加檢查點控制參數。
至少會有一個 WAL 段文件,而且通常不會超過 2 * checkpoint_segments + 1 個文件。每個段文件通常 16MB 大(當然您可以在製作伺服器的時候修改它)。您可以用這些訊息來估計 WAL 需要的空間。 通常,如果一個舊的日誌段文件不再需要了,那麼它將得到循環使用(重命名為順序的下一個可用段)。 如果由於短期的日誌輸出峰值,導致了超過 2 * checkpoint_segments + 1 個段文件, 那麼到系統再次回到這個限制之內的時候,多於的段文件會被刪除,而不是循環使用。
有兩個常用的 WAL 函數: LogInsert 和 LogFlush。 LogInsert 用於向共享內存中的 WAL 緩衝區裡加一條新的記錄。如果沒有空間存放新記錄, 那麼LogInsert 就不得不寫出(向內核緩存裡寫)一些填滿了的WAL緩衝。 我們可不想這樣,因為 LogInsert 用於每次資料庫低層修改(比如,記錄插入), 都要花在受影響的資料頁上持有一個排它鎖的時間,因為該操作需要越快越好;更糟糕的是, 寫 WAL 緩衝可能還會強制建立新的日誌段, 它花的時間甚至更多。通常,WAL 緩衝區應該由一個 LogFlush 請求來寫和沖刷, 在大部分時候它都是發生在交易提交的時候以確保交易記錄被沖刷到永久儲存器上去了。在那些日誌輸入量比較大的系統上, LogFlush 請求可能不夠頻繁,這樣就不能避免 LogInsert 進行寫操作。在這樣的系統上,我們應該透過修改配置參數 wal_buffers 的值來增加 WAL 緩衝區的數量。預設的 WAL 緩衝區數量是 8。增加這個數值將造成對應的共享內存使用量的增加。 (要注意的是,目前我們沒有什麼證據資料表明把 wal_buffers 的設置增大超過預設是值得的。)
commit_delay 定義了後端在使用 LogInsert 向日誌中寫了一條已提交的記錄之後, 在執行一次 LogFlush 之前休眠的毫秒數。 這樣的延遲可以允許其它的後端把它們提交的記錄追加到日誌中,這樣就可以用一次日誌同步把所有日誌沖刷到日誌中。 如果沒有打開fsync或者目前少於 commit_siblings 個其它後端處於活躍交易狀態的時候則不會發生休眠; 這樣就避免了在其它交易一時半會不會提交的情況下睡眠。 請注意在大多數平台上,休眠要求的分辯率是十毫秒, 所以任何介於 1 和 10000 微秒之間的非零 commit_delay 的作用都是一樣的。 適用這些參數的比較好的數值還不太清楚;我們鼓勵您多做試驗。
wal_sync_method 參數決定PostgreSQL 如何請求內核強制將 WAL 更新輸出到磁盤。只要滿足可靠性,那麼所有選項應該都是一樣的,但是哪個最快則可能和平台密切相關。 請注意如果您關閉了 fsync,那麼這個參數就無所謂了。
打開 wal_debug 配置參數(前提是 PostgreSQL編譯的時候打開了這個支援) 將導致每次 LogInsert 和 LogFlush WAL 調用都被記錄到伺服器日誌。這個選項以後可能會被更通用的機制取代。