支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

28.5. WAL組態設定 #

有幾個與WAL相關的組態參數會影響資料庫效能。本節說明它們的用途。有關設定伺服器組態參數的一般資訊,請參閱第 19 章

檢查點是在交易序列中的點,保證堆積和索引資料檔案已使用在該檢查點之前寫入的所有資訊進行更新。在檢查點時間,所有髒資料頁面都會刷新到磁碟,並且會將特殊的檢查點紀錄寫入 WAL 檔案。(變更紀錄先前已刷新到WAL檔案。)如果發生當機,當機恢復程序會查看最新的檢查點紀錄,以確定 WAL 中的點(稱為重做紀錄),從該點開始執行 REDO 操作。在該點之前對資料檔案所做的任何變更保證已在磁碟上。因此,在檢查點之後,不再需要包含重做紀錄之前的 WAL 片段,並且可以回收或移除。(當WAL正在進行歸檔時,必須先歸檔 WAL 片段,然後才能回收或移除。)

將所有髒資料頁面刷新到磁碟的檢查點要求可能會導致相當大的 I/O 負載。因此,會限制檢查點活動,以便 I/O 在檢查點開始時開始,並在下一個檢查點開始之前完成;這可以最大限度地減少檢查點期間的效能下降。

伺服器的檢查點程序會自動定期執行檢查點。每隔checkpoint_timeout 秒開始一次檢查點,或者如果即將超過max_wal_size,則以先到者為準。預設設定分別為 5 分鐘和 1 GB。如果自上次檢查點以來沒有寫入 WAL,即使經過了 checkpoint_timeout,也會略過新的檢查點。(如果正在使用 WAL 歸檔,並且您想對檔案歸檔的頻率設定一個下限,以限制潛在的資料遺失,則應調整archive_timeout 參數,而不是檢查點參數。)也可以使用 SQL 命令 CHECKPOINT 強制執行檢查點。

減少 checkpoint_timeout 和/或 max_wal_size 會導致更頻繁地發生檢查點。這可以更快地進行當機後恢復,因為需要重做的作業會更少。但是,必須權衡這一點與更頻繁地刷新髒資料頁面的成本增加。如果設定了full_page_writes(預設為設定),則還有另一個因素需要考慮。為了確保資料頁面一致性,每次檢查點後第一次修改資料頁面會導致記錄整個頁面內容。在這種情況下,較小的檢查點間隔會增加 WAL 的輸出量,部分抵消了使用較小間隔的目標,並且在任何情況下都會導致更多的磁碟 I/O。

檢查點的成本相當高,首先是因為它們需要寫出所有目前髒的緩衝區,其次是因為它們會導致額外的後續 WAL 流量,如上所述。因此,明智的做法是將檢查點參數設定得足夠高,以使檢查點不會過於頻繁地發生。作為檢查點參數的簡單健全性檢查,您可以設定checkpoint_warning 參數。如果檢查點發生的時間間隔小於 checkpoint_warning 秒,則會向伺服器日誌輸出訊息,建議增加 max_wal_size。偶爾出現此類訊息並不令人擔憂,但如果經常出現,則應增加檢查點控制參數。如果您沒有將 max_wal_size 設定得足夠高,則大型 COPY 傳輸等大量作業可能會導致出現許多此類警告。

為了避免 I/O 系統被大量的頁面寫入沖刷,在檢查點期間寫入髒緩衝區會分散在一段時間內。這段時間由 checkpoint_completion_target 控制,它表示檢查點間隔的分數(使用 checkpoint_timeout 配置)。I/O 速率會調整,以便檢查點在給定的 checkpoint_timeout 秒數的分數過去時完成,或在超過 max_wal_size 之前完成,以較早者為準。使用預設值 0.9,可以預期 PostgreSQL 會在下一個排定的檢查點之前(約為上一個檢查點持續時間的 90% 左右)完成每個檢查點。這會盡可能地分散 I/O,以便檢查點 I/O 負載在整個檢查點間隔內保持一致。這樣做的缺點是延長檢查點會影響復原時間,因為需要保留更多的 WAL 段以供復原時使用。如果使用者擔心復原所需的時間,可能希望減少 checkpoint_timeout,以便更頻繁地進行檢查點,但仍將 I/O 分散在檢查點間隔內。或者,可以減少 checkpoint_completion_target,但這會導致更密集的 I/O 時段(在檢查點期間)和較少 I/O 時段(在檢查點完成後但在下一個排定的檢查點之前),因此不建議這樣做。雖然 checkpoint_completion_target 可以設定為高達 1.0,但通常建議將其設定為不超過 0.9(預設值),因為檢查點除了寫入髒緩衝區之外還包含其他活動。設定為 1.0 很有可能導致檢查點無法按時完成,這會由於所需的 WAL 段數量出現意外變化而導致效能損失。

在 Linux 和 POSIX 平台上,checkpoint_flush_after 允許您強制檢查點寫入的 OS 頁面在可配置的位元組數後刷新到磁碟。否則,這些頁面可能會保留在 OS 的頁面快取中,從而在檢查點結束時發出 fsync 時導致停頓。此設定通常有助於減少交易延遲,但它也可能對效能產生不利影響;特別是對於大於 shared_buffers 但小於 OS 頁面快取的工作負載。

pg_wal 目錄中的 WAL 段檔案數量取決於 min_wal_sizemax_wal_size 和先前檢查點週期中產生的 WAL 數量。當不再需要舊的 WAL 段檔案時,它們會被移除或回收(也就是說,重新命名為編號序列中未來的段)。如果由於 WAL 輸出速率的短期高峰而超過 max_wal_size,則會移除不需要的段檔案,直到系統恢復到此限制以下。在此限制以下,系統會回收足夠的 WAL 檔案,以涵蓋直到下一個檢查點的估計需求,並移除其餘的 WAL 檔案。該估計基於先前檢查點週期中使用的 WAL 檔案數量的移動平均值。如果實際使用量超過估計值,移動平均值會立即增加,因此它會在一定程度上適應峰值使用量而不是平均使用量。min_wal_size 對於為未來使用而回收的 WAL 檔案數量設定了最小值;始終會為未來使用回收這麼多的 WAL,即使系統處於閒置狀態且 WAL 使用估計值表明只需要很少的 WAL。

獨立於 max_wal_size,始終會保留最近的 wal_keep_size MB 的 WAL 檔案加上一個額外的 WAL 檔案。此外,如果使用了 WAL 歸檔,則無法移除或回收舊段,直到它們被歸檔。如果 WAL 歸檔無法跟上 WAL 生成的速度,或者 archive_commandarchive_library 反覆失敗,則舊的 WAL 檔案將累積在 pg_wal 中,直到情況得到解決。使用複製槽的慢速或失敗的待命伺服器也會產生相同的效果(請參閱第 26.2.6 節)。

在封存復原或待命模式下,伺服器會定期執行重啟點這與正常運作中的檢查點類似:伺服器會強制將其所有狀態寫入磁碟,更新 pg_control 檔案以指示無需再次掃描已處理的 WAL 資料,然後回收 pg_wal 目錄中的任何舊 WAL 段檔案。重啟點的執行頻率不能高於主要伺服器上的檢查點,因為重啟點只能在檢查點記錄處執行。可以根據排程或外部請求要求重啟點。pg_stat_checkpointer 檢視中的 restartpoints_timed 計數器會計算第一個,而 restartpoints_req 則計算第二個。如果自上次執行的重啟點以來至少過去了 checkpoint_timeout 秒,或者先前嘗試執行重啟點已失敗,則當達到檢查點記錄時,會觸發排程的重啟點。在後一種情況下,下一個重啟點將在 15 秒後排定。由於類似於檢查點的原因,請求會觸發重啟點,但主要是如果 WAL 大小即將超過 max_wal_size。但是,由於執行重啟點的時間存在限制,因此在復原期間通常會超過 max_wal_size,最多可達一個檢查點週期的 WAL。(無論如何,max_wal_size 永遠不是一個硬性限制,因此您應該始終保留足夠的空間,以避免磁碟空間不足。)pg_stat_checkpointer 檢視中的 restartpoints_done 計數器會計算真正已執行的重啟點。

在某些情況下,當主要伺服器上的 WAL 大小快速增加時,例如在大量 INSERT 操作期間,備用伺服器上的 restartpoints_req 計數器可能會顯示出峰值增長。 這是因為由於 XLOG 消耗增加而產生建立新重新啟動點的要求無法執行,原因是自上次重新啟動點以來的安全檢查點記錄尚未在備用伺服器上重播。 此行為是正常的,不會導致系統資源消耗增加。 在與重新啟動點相關的計數器中,只有 restartpoints_done 計數器表示已花費顯著的系統資源。

以下是兩個常用的內部WAL函式:XLogInsertRecordXLogFlushXLogInsertRecord 用於將新紀錄放入WAL共享記憶體中的緩衝區。 如果沒有空間容納新紀錄,XLogInsertRecord 必須寫入(移動到核心快取)一些已滿的WAL緩衝區。 這是不可取的,因為在每次資料庫低階修改時(例如,行插入),XLogInsertRecord 都會使用,並且會對受影響的資料頁面持有獨佔鎖定,因此操作需要盡可能快。 更糟的是,寫入WAL緩衝區也可能強制建立新的 WAL 段,這需要花費更多時間。 通常,WAL緩衝區應該由 XLogFlush 請求寫入和刷新,XLogFlush 請求主要在事務提交時發出,以確保事務記錄被刷新到永久儲存體。 在 WAL 輸出高的系統上,XLogFlush 請求可能不會經常發生,以防止 XLogInsertRecord 必須執行寫入。 在這種系統上,應該通過修改 wal_buffers 參數來增加WAL緩衝區的數量。 當 full_page_writes 設定且系統非常繁忙時,將 wal_buffers 設定為更高的值將有助於在每次檢查點之後立即平滑回應時間。

commit_delay 參數定義了群組提交領導程序在 XLogFlush 中獲取鎖定後休眠多少微秒,而群組提交追隨者則在領導者之後排隊。 此延遲允許其他伺服器進程將其提交記錄添加到 WAL 緩衝區,以便所有這些記錄都將由領導者的最終同步操作刷新。 如果未啟用 fsync,或者當前活動事務中的其他會話少於 commit_siblings,則不會發生休眠;這避免了在不太可能有其他會話很快提交時休眠。 請注意,在某些平台上,休眠請求的解析度為十毫秒,因此任何介於 1 到 10000 微秒之間的非零 commit_delay 設定都具有相同的效果。 另請注意,在某些平台上,休眠操作可能比參數請求的時間稍長。

由於 commit_delay 的目的是允許每次刷新操作的成本在並行提交的事務中分攤(可能會以事務延遲為代價),因此在明智地選擇設定之前,有必要量化該成本。 成本越高,commit_delay 在提高事務吞吐量方面預期的效果就越大,直到某個點。 pg_test_fsync 程式可用於測量單個 WAL 刷新操作所需的平均時間(以微秒為單位)。 在單個 8kB 寫入操作後,程式報告刷新所需的平均時間的一半通常是 commit_delay 的最有效設定,因此建議將該值作為針對特定工作負載進行優化時的起點。 雖然在將 WAL 儲存在高延遲旋轉磁碟上時,調整 commit_delay 特別有用,但即使在使用具有非常快的同步時間的儲存媒體(例如固態硬碟或具有電池備份寫入快取的 RAID 陣列)上,益處也可能很顯著;但這肯定應該針對代表性的工作負載進行測試。 在這種情況下,應使用更高的 commit_siblings 值,而在更高延遲的媒體上,較小的 commit_siblings 值通常很有用。 請注意,commit_delay 的設定太高可能會使事務延遲增加到 total transaction throughput 受到影響。

commit_delay 設定為零(預設值)時,仍然可能發生一種群組提交形式,但每個群組將僅由在先前刷新操作(如果有的話)發生的窗口期間達到需要刷新其提交記錄的點的會話組成。 在較高的客戶端數量下,往往會出現gangway effect,因此即使 commit_delay 為零,群組提交的效果也會變得顯著,因此顯式設定 commit_delay 往往幫助較少。 只有在 (1) 存在一些並行提交的事務,並且 (2) 吞吐量在某種程度上受到提交率的限制時,設定 commit_delay 才能有所幫助;但在高旋轉延遲的情況下,此設定對於僅有兩個客戶端(即,一個提交客戶端和一個同級事務)增加事務吞吐量可能有效。

wal_sync_method 參數確定 PostgreSQL 將如何要求核心強制WAL更新到磁碟。 除了 fsync_writethrough 之外,所有選項在可靠性方面都應該相同,fsync_writethrough 有時甚至可以在其他選項不執行此操作時強制刷新磁碟快取。 但是,哪一個最快在很大程度上取決於平台。 您可以使用 pg_test_fsync 程式測試不同選項的速度。 請注意,如果已關閉 fsync,則此參數無關緊要。

啟用 wal_debug 配置參數(前提是 PostgreSQL 已編譯並支援它)將導致每個 XLogInsertRecordXLogFlushWAL呼叫被記錄到伺服器日誌中。 將來此選項可能會被更通用的機制取代。

有兩個內部函式可用於將 WAL 資料寫入磁碟:XLogWriteissue_xlog_fsync。當啟用track_wal_io_timing時,XLogWrite 寫入和 issue_xlog_fsync 同步 WAL 資料到磁碟的總時間量,會分別以 pg_stat_wal 中的 wal_write_timewal_sync_time 來計數。XLogWrite 通常由 XLogInsertRecord (當 WAL 緩衝區中沒有新紀錄的空間時)、XLogFlush 和 WAL writer 呼叫,以將 WAL 緩衝區寫入磁碟並呼叫 issue_xlog_fsyncissue_xlog_fsync 通常由 XLogWrite 呼叫,以將 WAL 檔案同步到磁碟。如果 wal_sync_methodopen_datasyncopen_sync,則 XLogWrite 中的寫入操作會保證將寫入的 WAL 資料同步到磁碟,並且 issue_xlog_fsync 不執行任何操作。如果 wal_sync_methodfdatasyncfsyncfsync_writethrough,則寫入操作會將 WAL 緩衝區移動到核心快取,並且 issue_xlog_fsync 將它們同步到磁碟。無論 track_wal_io_timing 的設定如何,XLogWrite 寫入和 issue_xlog_fsync 將 WAL 資料同步到磁碟的次數,也會分別以 pg_stat_wal 中的 wal_writewal_sync 來計數。

recovery_prefetch 參數可用於減少恢復期間的 I/O 等待時間,方法是指示核心啟動對即將需要但目前不在 PostgreSQL 緩衝池中的磁碟區塊的讀取。maintenance_io_concurrencywal_decode_buffer_size 設定分別限制預取並行性和距離。預設情況下,它設定為 try,這會在可以使用 posix_fadvise 的系統上啟用該功能。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的地方,請使用此表單報告文件問題。