2025年9月25日: PostgreSQL 18 釋出!
支援版本:當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6

64.1. 通用 WAL 記錄 #

雖然所有內建的 WAL 日誌記錄模組都有自己的 WAL 記錄型別,但還有一個通用的 WAL 記錄型別,它以通用方式描述頁面的更改。

注意

邏輯解碼期間,通用 WAL 記錄會被忽略。如果您的擴充套件需要邏輯解碼,請考慮使用自定義 WAL 資源管理器。

用於構造通用 WAL 記錄的 API 定義在 access/generic_xlog.h 中,實現在 access/transam/generic_xlog.c 中。

要使用通用 WAL 記錄機制執行 WAL 日誌記錄的資料更新,請執行以下步驟:

  1. state = GenericXLogStart(relation) — 為給定的關係開始構造一個通用 WAL 記錄。

  2. page = GenericXLogRegisterBuffer(state, buffer, flags) — 註冊要在當前通用 WAL 記錄中修改的緩衝區。此函式返回指向緩衝區頁面臨時副本的指標,修改應在此副本上進行。(請勿直接修改緩衝區內容。)第三個引數是一個適用於該操作的標誌位掩碼。目前唯一的標誌是 GENERIC_XLOG_FULL_IMAGE,它指示 WAL 記錄應包含完整頁面映像而不是增量更新。通常,如果頁面是新的或已完全重寫,則會設定此標誌。如果 WAL 日誌記錄的操作需要修改多個頁面,則可以重複呼叫 GenericXLogRegisterBuffer

  3. 在上一階段獲得的頁面映像上應用修改。

  4. GenericXLogFinish(state) — 將更改應用於緩衝區併發出通用 WAL 記錄。

在上述任何步驟之間,都可以透過呼叫 GenericXLogAbort(state) 來取消 WAL 記錄的構造。這將丟棄對頁面映像副本的所有更改。

使用通用 WAL 記錄機制時,請注意以下幾點:

  • 不允許直接修改緩衝區!所有修改都必須在從 GenericXLogRegisterBuffer() 獲取的副本上進行。換句話說,建立通用 WAL 記錄的程式碼本身不應呼叫 BufferGetPage()。但是,由呼叫者負責在適當的時候固定/取消固定和鎖定/解鎖緩衝區。從 GenericXLogRegisterBuffer() 呼叫之前直到 GenericXLogFinish() 呼叫之後,必須持有對每個目標緩衝區的獨佔鎖。

  • 緩衝區的註冊(步驟 2)和頁面映像的修改(步驟 3)可以自由混合,即這兩個步驟可以按任何順序重複。請記住,在重放期間獲取鎖時,緩衝區應按與獲取鎖相同的順序進行註冊。

  • 可以為通用 WAL 記錄註冊的緩衝區的最大數量是 MAX_GENERIC_XLOG_PAGES。如果超出此限制,將丟擲錯誤。

  • 通用 WAL 假定要修改的頁面具有標準佈局,特別是 pd_lowerpd_upper 之間沒有有用的資料。

  • 由於您正在修改緩衝區頁面的副本,因此 GenericXLogStart() 不會啟動臨界區。因此,您可以在 GenericXLogStart()GenericXLogFinish() 之間安全地進行記憶體分配、錯誤丟擲等操作。唯一的實際臨界區存在於 GenericXLogFinish() 內部。在發生錯誤退出時,也不需要擔心呼叫 GenericXLogAbort()

  • GenericXLogFinish() 負責標記緩衝區為髒並設定其 LSN。您無需顯式執行此操作。

  • 對於未記錄的(unlogged)關係,所有操作都相同,只是不會發出實際的 WAL 記錄。因此,您通常不需要對未記錄的關係進行任何顯式檢查。

  • 通用 WAL 重放函式將按照註冊的相同順序獲取緩衝區的獨佔鎖。重放完所有更改後,將按相同順序釋放鎖。

  • 如果為註冊的緩衝區未指定 GENERIC_XLOG_FULL_IMAGE,則通用 WAL 記錄將包含舊頁面映像和新頁面映像之間的增量。此增量基於逐位元組比較。對於頁面內移動資料的場景,這不是很緊湊,未來可能會有所改進。

提交更正

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