為什麼我的 RDS for PostgreSQL 資料庫執行個體中有複寫延遲和錯誤?

上次更新日期:2022 年 6 月 22 日

我在 Amazon Relational Database Service (Amazon RDS) for PostgreSQL 執行個體中遇到複寫錯誤。

簡短描述

您可以將僅供讀取複本新增至執行個體,以擴展 Amazon RDS for PostgreSQL 資料庫執行個體的讀取。RDS for PostgreSQL 使用 PostgreSQL 原生串流複寫來建立來源資料庫執行個體的唯讀複本。此僅供讀取複本資料庫執行個體是來源資料庫執行個體的非同步建立實體複本。這表示有時複本無法跟上主要資料庫執行個體。因此,可能會發生複寫延遲。複本資料庫是由特殊連線建立的,該連線會將來源資料庫執行個體的預寫日誌 (WAL) 資料傳輸至僅供讀取複本。因此,僅供讀取複本會檢查 WAL 日誌,以複寫主要執行個體上所做的變更。當僅供讀取複本在主要執行個體上找不到 WAL 時,僅供讀取複本會從 Amazon Simple Storage Service (Amazon S3) 中的已封存 WAL 資料復原。如需詳細資訊,請參閱串流複寫如何在不同的 RDS for PostgreSQL 版本中運作

您可以藉由檢視 Amazon RDS ReplicaLag 指標,監控 Amazon CloudWatch 中的複寫延遲。此指標會顯示僅供讀取複本已落後其來源資料庫執行個體多少。Amazon RDS 會監控僅供讀取複本的複寫狀態。然後,如果複寫因為任何原因而停止,Amazon RDS 主控台中的 Replication State (複寫狀態) 欄位會更新為 Error (錯誤)。ReplicaLag 指標會指出僅供讀取複本與來源資料庫執行個體保持同步的程度,以及來源資料庫執行個體與特定僅供讀取執行個體之間的延遲量。

解決方案

當複本延遲增加時,您可能會在 RDS for PostgreSQL 錯誤日誌檔中看到下列其中一個錯誤:

  • 串流複寫已停止:當主要執行個體和複本執行個體之間的串流複寫中斷時,您會收到此錯誤。在這種情況下,複寫會從 Amazon S3 的封存位置開始重新執行,進一步增加複本延遲。
  • 串流複寫已終止:當複寫停止超過連續 30 天 (手動或由於複寫錯誤) 時,您會收到此錯誤。在這種情況下,Amazon RDS 會終止主要資料庫執行個體和所有僅供讀取複本之間的複寫,以避免主要執行個體上的儲存需求增加和更久的容錯移轉時間。

即使在複寫終止之後,僅供讀取複本執行個體仍可使用。但是無法繼續複寫,因為僅供讀取複本所需的交易日誌會在複寫終止之後從主要執行個體中刪除。

複本延遲增加的最常見原因如下:

  • 主要執行個體和複本執行個體之間的組態差異
  • 主要執行個體上的大量寫入工作負載
  • 長時間執行的交易
  • 主要執行個體資料表上的獨佔鎖定
  • 損毀或遺失 WAL 檔案
  • 網路問題
  • 參數設定不正確
  • 沒有交易

主要執行個體和讀取複本之間的組態差異

不正確的複本執行個體組態會影響複寫效能。僅供讀取複本可處理與來源執行個體類似的寫入工作負載,以及其他讀取查詢。因此,請使用相同或更高執行個體類別和儲存類型的複本做為來源執行個體。由於複本必須重新執行與來源執行個體相同的寫入活動,因此使用較低執行個體類別複本可能會造成複本高延遲並增加複寫延遲。不相符的儲存組態也會增加複寫延遲。

主要執行個體上的大量寫入工作負載

主要執行個體上的大量寫入工作負載可能會產生大量湧入的 WAL 檔案。增加 WAL 檔案數目以及在僅供讀取複本上重新執行這些檔案可能會降低整體複寫效能。因此,當您看到複本延遲增加時,請務必檢查主要執行個體上的寫入活動。您可以使用 CloudWatch 指標或增強型監控來分析此工作負載。檢視 TransactionLogsDiskUsageTransactionLogsGenerationWriteIOPSWriteThroughputWriteLatency 的值,以找出來源執行個體是否處於大量寫入工作負載下。您也可以在輸送量層級檢查瓶頸。每個執行個體類型都有其專用輸送量。如需詳細資訊,請參閱資料庫執行個體類別的硬體規格

若要避免此問題,請控制並散佈來源執行個體的寫入活動。並非一起執行許多寫入活動,而是將您的任務分解為較小的任務服務包,然後將這些服務包平均分配到多個交易中。您可以針對指標 (例如 WritelatencyWriteIOPS) 使用 CloudWatch 提醒,在來源執行個體上有大量寫入時發出通知。

長時間執行的交易

在資料庫中長時間執行的作用中交易可能會干擾 WAL 複寫程序,進而增加複寫延遲。因此,請務必使用 PostgreSQL pg_stat_activity 檢視來監控作用中交易的執行時間。

在主要執行個體上執行類似於以下內容的查詢,以尋找長時間執行之查詢的處理序 ID (PID):

SELECT datname, pid,usename, client_addr, backend_start,
xact_start, current_timestamp - xact_start AS xact_runtime, state,
backend_xmin FROM pg_stat_activity WHERE state='active';

識別查詢的 PID 之後,您可以選擇結束查詢。

在主要執行個體上執行類似於以下內容的查詢,以終止查詢:

SELECT pg_terminate_backend(PID);

您也可以選擇重新寫入或調整查詢,以避免長時間執行的交易。

主要執行個體資料表上的獨佔鎖定

當您在主要執行個體上執行命令時,例如 DROP TABLE、TRUNCATE、REINDEX、VACUUM FULL、REFRESH MATERIALIZED VIEW (不同時執行),PostgreSQL 會處理存取獨佔鎖定。此鎖定可防止所有其他交易在鎖定的保留期間內存取資料表。通常,資料表會保持鎖定狀態,直到交易結束為止。此鎖定活動會記錄在 WAL 中,然後由僅供讀取複本重新執行並保留。資料表在「存取獨佔」鎖定下保留的時間越長,複寫延遲就越長。

為了避免這個問題,最佳實務是定期查詢 pg_locks and pg_stat_activity 目錄資料表來監控交易。

範例:

SELECT pid, usename, pg_blocking_pids(pid) AS blocked_by, QUERY AS blocked_query<br>FROM pg_stat_activity<br>WHERE cardinality(pg_blocking_pids(pid)) > 0;

損毀或遺失 WAL 檔案

損毀或遺失 WAL 檔案會導致複本延遲。在這種情況下,您會在 PostgreSQL 日誌中看到一個錯誤,指出 WAL 無法開啟。您可能還會看到錯誤「請求的 WAL 區段 XXX 已移除」。

網路問題

主要執行個體和複本執行個體之間的網路中斷可能會造成串流複寫發生問題,進而導致複本延遲增加。

參數設定不正確

伺服器組態參數群組中某些自訂參數的設定不正確可能會造成複本延遲增加。以下是一些您必須正確設定的參數:

  • wal_keep_segments:此參數會指定主要執行個體在 pg_wal 目錄中保留的 WAL 檔案數目。此參數的預設值設定為 32。如果此參數未設定為足以供部署使用的值,僅供讀取複本可能落後,導致串流複寫停止。在此情況下,RDS 會產生複寫錯誤,並透過從 S3 重新執行主要執行個體的已封存 WAL 資料,開始在僅供讀取複本上復原。此復原程序會繼續進行,直到僅供讀取複本可以繼續串流複寫為止。
    注意:在 PostgreSQL 第 13 版中,wal_keep_segments 參數的名稱是 wal_keep_size。此參數的用途與 wal_keep_segments 相同。不過,此參數的預設值是以 MB (2048 MB) 為單位定義,而非檔案數目。
  • max_wal_senders:此參數會指定主要執行個體透過串流複寫通訊協定可以同時支援的連線數目上限。此參數適用於 RDS for PostgreSQL 13 和更高版本的預設值是 20。此參數應設定為略高於僅供讀取複本實際數目的值。如果將此參數設定為小於僅供讀取複本數目的值,則複寫會停止。
  • hot_standby_feedback:此參數會指定複本執行個體是否會針對目前在複本執行個體中執行的查詢,傳送反饋給主要執行個體。藉由開啟此參數,您可以在來源執行個體建立下列錯誤訊息,並在相關資料表上延後 VACUUM 操作,除非複本執行個體中的讀取查詢已完成。因此,已開啟 Hot_standby_feedback 的複本執行個體可以提供長時間執行的查詢。但是,此參數可能會在來源執行個體中膨脹資料表。請務必監視複本執行個體中長時間執行的查詢,以避免嚴重問題,例如主要執行個體中的儲存空間不足和交易 ID 環繞。
ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed
  • max_standby_streaming_delay/max_standby_archive_delay:您可以在複本執行個體上啟用參數,例如 max_standby_archive_delaymax_standby_streaming_delay,以完成長時間執行讀取查詢。如果在複本上執行讀取查詢時修改來源資料,這些參數會暫停複本中的 WAL 重新執行。這些參數的值為 -1,可讓 WAL 重新執行等到讀取查詢完成。但是這樣的暫停會無限增加複寫延遲,並且由於 WAL 累積而導致來源的高儲存消耗。

沒有交易

如果來源資料庫執行個體上沒有發生任何使用者交易,則 PostgreSQL 僅供讀取複本會報告最多五分鐘的複寫延遲。


此文章是否有幫助?


您是否需要帳單或技術支援?