為什麼我在 Amazon RDS for PostgreSQL 上收到「裝置上沒有剩餘空間」或「DiskFull」錯誤?

3 分的閱讀內容
0

我擁有適用於 PostgreSQL 資料庫的 Amazon Relational Database Service (Amazon RDS)。資料庫執行個體的可用儲存空間正在減少,我收到下列錯誤: 「錯誤訊息: PG::DiskFull: 錯誤:無法延伸檔案 "base/16394/5139755": 裝置上沒有剩餘空間。提示: 檢查可用的磁碟空間。」

解決方法

**注意:**當您的工作負載可預測時,接著啟用執行個體的儲存空間自動擴展功能。透過儲存體自動擴展功能,Amazon RDS 可在可用資料庫空間不足時自動擴展儲存空間。

若要監控儲存空間,請檢查 FreeStorageSpace Amazon CloudWatch 指標為可用儲存空間設定 CloudWatch 警示後,您會在空間開始減少時收到通知。如果收到警示,請檢查下列使用 Amazon RDS 資料庫執行個體儲存空間的資源:

  • 由 PostgreSQL 交易建立的暫存資料表或檔案
  • 資料檔案
  • 預先寫入日誌 (WAL)
  • 複寫插槽
  • 保留時間過長的資料庫日誌 (例如錯誤檔案)
  • 支援 RDS 資料庫執行個體一致狀態的其他資料庫或 Linux 檔案

如果您的資料庫執行個體消耗的儲存空間超過預期,請執行下列疑難排解動作。

檢查資料庫日誌檔案的大小

依預設,Amazon RDS for PostgreSQL 錯誤日誌的保留值為 4,320 分鐘 (三天)。由於大型日誌的工作負載較高或日誌過多,因此所以可能會使用更多空間。若要變更系統日誌保留期,請使用與資料庫執行個體相關聯的資料庫參數群組中的 rds.log_retention_period 參數。例如,如果您將值設定為 1,440,Amazon RDS 會保留日誌一天。如需詳細資訊,請參閱 RDS for PostgreSQL 資料庫日誌檔案

若要減少過多的日誌,請變更資料庫參數群組中的錯誤報告和日誌參數。此動作會導致日誌檔案大小縮小。如需詳細資訊,請參閱 PostgreSQL 網站上的 19.8 錯誤報告和日誌記錄

檢查暫存檔案

暫存檔案是 Amazon RDS 儲存在每個後端或工作階段連線中的檔案。Amazon RDS 使用這些檔案作為資源集區。若要檢閱暫存檔案統計資料,請執行下列命令:

psql=> SELECT datname, temp_files AS "Temporary files",temp_bytes AS "Size of temporary files" FROM pg_stat_database ;

**重要:**在 pg_stat_database 檢視收集彙整統計資料中的 temp_filestemp_bytes 資料欄。Amazon RDS 僅在立即關機、伺服器當機或時間點復原 (PITR) 後才會重設這些計數器。因此,最佳實務是監控這些檔案的數量和大小變化,而不是僅檢視輸出。

Amazon RDS 會為排序、雜湊和暫存查詢結果建立暫時檔案。若要追蹤暫存資料表或檔案的建立作業,請在自訂參數群組中,將 log_temp_files 設定為 0 以記錄所有暫存檔案資訊。log_temp_files 預設會設定為 -1,因此 Amazon RDS 不會記錄暫存檔案。如果將 log_temp_files 設定為正值,則 Amazon RDS 只會記錄等於或大於該千位元組數的檔案。

在查詢中使用 EXPLAIN ANALYZE 來檢閱磁碟排序。在日誌輸出中,檢查查詢建立的暫存檔案的大小。如需詳細資訊,請參閱使用 work_mem 調整 PostgreSQL 中的排序操作

檢查交易日誌磁碟使用量是否持續增加

檢查TransactionLogsDiskUsage 指標以檢視交易 WAL 所使用的磁碟空間。交易日誌磁碟使用量可能會因下列原因而增加:

  • 產生額外的 WAL 的寫入和更新作業的較高資料庫負載
  • 相同 AWS 區域中的複本之串流讀取複本延遲,或讀取複本處於儲存空間已滿狀態
  • 複寫插槽

AWS Database Migration Service (AWS DMS) 會將複寫插槽建立為邏輯解碼的一部分。對於邏輯複寫,插槽參數 rds.logical_replication 會設為 1。複寫插槽會保留 WAL 檔案,直到外部取用者消耗檔案為止。範例取用者包括 pg_recvlogic、擷取、轉換和載入 (ETL) 工作,以及 AWS DMS。

如果您將 rds.logical_replication 參數值設為 1,則 Amazon RDS 會設定wal_levelmax_wal_sendersmax_replication_slotsmax_connections 參數。這些參數變更可能會增加 WAL 的產生。最佳實務為僅在使用邏輯插槽時才設定 rds.logical_replication 參數。如果沒有保留的 WAL 檔案的取用者,則交易日誌磁碟使用量會增加,而可用的儲存空間會持續減少。

若要檢查複寫插槽的顯示狀態和大小,請執行下列查詢:

  • PostgreSQL 第 9 版:

    psql=> SELECT slot_name, pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(),restart_lsn)) AS replicationSlotLag, active FROM pg_replication_slots ;
  • PostgreSQL 第 10 版及更新版本:

    psql=> SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag, active FROM pg_replication_slots ;

範例輸出結果:

slot_name                                                      | replicationslotlag | active---------------------------------------------------------------+--------------------+--------
xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d    | 129 GB             | f
7pajuy7htthd7sqn_00013322_a27bcebf_7d0f_4124_b336_92d0fb9f5130 | 704 MB             | t
zp2tkfo4ejw3dtlw_00013322_03e77862_689d_41c5_99ba_021c8a3f851a | 624 MB             | t

將作用中狀態設定為 f (false) 的複寫插槽不會被耗用。在此範例中,xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d 顯示具有 f 作用中的狀態。此插槽不會主動被使用,而是使用 129 GB 的交易檔案。

若要捨棄未使用的插槽,請執行下列查詢:

psql=> SELECT pg_drop_replication_slot('YOUR_SLOTNAME');

**注意:**使用插槽名稱取代 YOUR_SLOTNAME

範例輸出結果:

psql=> SELECT pg_drop_replication_slot('xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

如果 AWS DMS 任務是取用者且不再需要該任務,則請刪除該任務並手動捨棄複寫插槽。

檢查跨區域或相同區域讀取複本的狀態

**注意:**只有在 PostgreSQL 14.1 或更新版本上執行相同區域讀取複本時,才能使用下列解決方案。

當您使用跨區域或相同區域讀取複寫時,Amazon RDS 會在主要執行個體上建立實體複寫插槽。讀取複本失敗可能會影響主要資料庫執行個體上的儲存空間。當 WAL 檔案未在讀取複本中複製時,就會發生這種情況。檢查 OldestReplicationSlotLagTransactionLogsDiskUsage 指標以確定延遲最多的複本落後於進度的程度。您還可以查看 WAL 資料使用了多少的儲存空間。

若要檢查讀取複本的狀態,請執行下列查詢:

psql=> SELECT * FROM pg_replication_slots;

如需有關 pg_replication_slots 的詳細資訊,請參閱 PostgreSQL 網站上的 52.19 pg_replication_slots。如果輸出具有設為 f 的作用中狀態,則插槽不會用於複寫。

您也可以在來源執行個體上使用 pg_stat_replication 以檢查複寫的統計資料。如需詳細資訊,請參閱 PostgreSQL 網站上的資料表 27.14. pg_stat_replication 檢視

檢查無效資料列膨脹或不當去除的情形

在標準 PostgreSQL 作業中,PostgreSQL 不會移除使用者刪除的或 UPDATE 從其資料表中停用的無效資料列 (元組)。對於 Multi-Version Concurrency Control (MVCC),當執行 DELETE 作業時,資料列不會立即從資料檔案中移除。反之,PostgreSQL 在標頭中設定 xmax 欄位,以將該資料列標記為已刪除。更新首先標記要刪除的資料列,然後執行插入作業。這可讓您在不同的交易之間以最小鎖定並行。因此,PostgreSQL 會在 MVCC 流程中保留不同的資料列版本。

未清除的無效資料列會保留在資料檔案中,但對交易仍不可見。這些資料列可能會導致磁碟空間問題。如果資料表有許多 DELETEUPDATE 作業,則無效元組可能會使用大量磁碟空間 (膨脹)。

使用 VACUUM 作業可釋放無效元組所使用的儲存空間。請注意,VACUUM 不會將可用儲存空間釋放到檔案系統。若要將儲存空間釋放到檔案系統,請使用 VACUUM FULL。請注意,當您執行 VACUUM FULL 時,PostgreSQL 會將存取專用鎖定套用至資料表。因為 VACUUM FULL 會寫入資料表的新副本,並且不會在作業完成之前釋放現有副本,所以此方法需要額外的磁碟空間。最佳實務為當您必須從資料表回收大量空間時,才會使用 VACUUM FULL。在經常更新的資料表上執行定期 VACUUM 或 AUTOVACUUM 作業,同樣屬於最佳實務。如需詳細資訊,請參閱 PostgreSQL 網站上的 VACUUM

若要檢查預估的無效元組數量,請使用 pg_stat_all_tables 檢視。如需詳細資訊,請參閱 PostgreSQL 網站上的 資料表 27.29. pg_stat_all_tables 檢視。在下列範例資料表中,n_dead_tup 記錄中有 1,999,952 個無效元組:

psql => SELECT * FROM pg_stat_all_tables WHERE relname='test';
-[ RECORD 1 ]-------+------------------------------
relid               | 16395
schemaname          | public
relname             | test
seq_scan            | 3
seq_tup_read        | 5280041
idx_scan            |
idx_tup_fetch       |
n_tup_ins           | 2000000
n_tup_upd           | 0
n_tup_del           | 3639911
n_tup_hot_upd       | 0
n_live_tup          | 1635941
n_dead_tup          | 1999952
n_mod_since_analyze | 3999952
last_vacuum         |
last_autovacuum     | 2024-08-16 04:49:52.399546+00
last_analyze        | 2024-08-09 09:44:56.208889+00
last_autoanalyze    | 2024-08-16 04:50:22.581935+00
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 1
autoanalyze_count   | 1


psql => VACUUM TEST;

檢查孤立檔案

當沒有物件指向資料庫目錄中存在的檔案時,可能會產生孤立檔案。如果您的執行個體儲存空間不足,或者在 ALTER TABLEVACUUM FULLCLUSTER 等作業期間發生引擎當機,即可能會發生這種情況。若要檢查是否有孤立檔案,請完成下列步驟:

  1. 登入每個資料庫中的 PostgreSQL。

  2. 若要取得資料庫使用的大小,請執行下列查詢:

    psql=> SELECT pg_size_pretty(pg_database_size('DATABASE_NAME'));

    **注意:**使用您的資料庫名稱取代 DATABASE_NAME

  3. 若要取得資料庫的實際大小,請執行下列查詢:

    psql=> SELECT pg_size_pretty(SUM(pg_relation_size(oid))) FROM pg_class;
  4. 從先前命令的輸出來比較資料庫的使用和實際大小。如果差異很大,則孤立檔案可能正在使用儲存空間。

相關資訊

使用適用於 Amazon RDS for PostgreSQL 的讀取複本

自動化監控工具