Amazon RDS for PostgreSQL で「デバイスに空き容量がありません」または「DiskFull」エラーが表示されるのはなぜですか?

最終更新日: 2022 年 6 月 23 日

PostgreSQL データベース用の小規模 Amazon Relational Database Service (Amazon RDS) があります。インスタンスの空きストレージ容量が減少しており、次のエラーが表示されます。

"Error message: PG::DiskFull: ERROR: could not extend file "base/16394/5139755": No space left on device.HINT: Check free disk space."

DiskFull エラーを解決し、ストレージの問題を回避したいです。

簡単な説明

Amazon RDS DB インスタンスストレージは、以下によって使用されます。

  • PostgreSQL トランザクションによって作成された一時テーブルまたはファイル
  • データファイル
  • 先書きログ (WAL ログ)
  • レプリケーションスロット
  • 長期間保存されている DB ログ (エラーファイル)
  • RDS DB インスタンスの一貫した状態をサポートする他の DB ファイルまたは Linux ファイル

解決方法

1.    Amazon CloudWatch を使用して、FreeStorageSpace メトリクスで DB ストレージ容量をモニタリングします。ストレージの空き容量に対して CloudWatch アラームを設定すると、容量が減少し始めるときに通知を受け取ります。アラームが表示された場合は、前述のストレージ問題の原因を確認してください。

2.    それでも DB インスタンスが予想より多くのストレージを消費している場合は、以下を確認してください。

  • DB ログファイルのサイズ
  • 一時ファイルの有無
  • トランザクションログのディスク使用量が常に増加しているか
  • レプリケーションスロット:
    • 物理レプリケーションスロットは、PostgreSQL 14.1 以降のバージョンで実行されている場合にのみ、クロスリージョンリードレプリカまたは同一リージョンリードレプリカによって作成されます。
    • 論理レプリケーションスロットはレプリカまたはサブスクライバー用に作成されます
  • 実行されない行の肥大化または不適切な削除
  • 孤立したファイルの有無

3.    ワークロードが予測可能な場合は、インスタンスのストレージ自動スケーリングを有効にします。ストレージの自動スケーリングを有効にすると、Amazon RDS によってデータベースの空き容量が不足していることが検出されると、ストレージは自動的にスケーリングされます。Amazon RDS では、次の要因が当てはまる場合に、自動スケーリングが有効な DB インスタンスのストレージ変更が開始されます。

  • 空き容量が、割り当てられたストレージの 10% 未満である。
  • ストレージが少ない状態が 5 分以上継続している。
  • インスタンスでの最後のストレージ変更またはストレージの最適化が完了してから 6 時間以上が経過している (どちらか長い方)。

最大ストレージしきい値を設定することで、DB インスタンスの自動スケーリングに制限を設定できます。詳細については、「mazon RDS ストレージの自動スケーリングによる容量の自動管理」を参照してください。

DB ログファイルのサイズを確認する

デフォルトでは、Amazon RDS for PostgreSQL エラーログファイルの保持期間は 4,320 分 (3 日) です。ログファイルが大きいと、ワークロードが高くなるか、ログが過剰になるため、より多くの容量が使用される可能性があります。DB インスタンスに関連付けられている DB パラメータグループの rds.log_retention_period パラメータを使用して、システムログの保持期間を変更できます。たとえば、値を 1440 に設定すると、ログは 1 日間保持されます。詳細については、「PostgreSQL データベースのログファイル」を参照してください。

また、DB パラメータグループのエラーレポートとロギングパラメータを変更して、過剰なロギングを減らすこともできます。これにより、ログファイルのサイズが小さくなります。詳細については、「エラー報告とロギング」を参照してください。

一時ファイルを確認する

一時ファイルは、バックエンドまたはセッション接続ごとに保存されるファイルです。これらのファイルはリソースプールとして使用されます。次のようなコマンドを実行して、一時ファイルの統計を確認します。

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

重要: ビュー pg_stat_database の列 temp_files および temp_bytes は、統計を集計 (累積) で収集しています。これらのカウンタはサーバー起動時のリカバリによってのみリセットされるため、これは仕様によるものです。つまり、カウンタは、即時のシャットダウン、サーバーのクラッシュ、またはポイントインタイムリカバリ (PITR) の後にリセットされます。このため、出力のみを確認するのではなく、これらのファイルの数とサイズの増加をモニタリングすることをお勧めします。

一時ファイルは、並べ替え、ハッシュ、および一時的なクエリ結果用に作成されます。一時テーブルまたはファイルの作成を追跡するには、カスタムパラメータグループに log_temp_files を設定します。このパラメータは、一時ファイルの名前とサイズのログ記録をコントロールします。log_temp_files 値を 0 に設定すると、すべての一時ファイル情報がログに記録されます。このパラメータを正の値に設定した場合、指定されたキロバイト数以上のサイズのファイルのみがログに記録されます。デフォルト設定は -1 で、一時ファイルのロギングは無効になります。

また、クエリの EXPLAIN ANALYZE を使用してディスクの並べ替えを確認することもできます。ログ出力を確認すると、クエリによって作成された一時ファイルのサイズを確認できます。詳細については、データベースのアクティビティをモニタリングするための PostgreSQL ドキュメントを参照してください。

トランザクションログのディスク使用量が常に増加しているか確認する

TransactionLogsDiskUsage の CloudWatch メトリクスは、トランザクション WAL によって使用されるディスク容量を表します。トランザクションログのディスク使用量の増加は、以下の原因で発生する可能性があります。

  • 高い DB 負荷 (追加の WAL を生成する書き込みおよび更新)
  • ストリーミングリードレプリカラグ (同じリージョン内のレプリカ) またはストレージがフル状態のリードレプリカ
  • レプリケーションスロット

レプリケーションスロットは、AWS Database Migration Service (AWS DMS) の論理デコード機能の一部として作成できます。論理レプリケーションの場合、スロットパラメータ rds.logical_replication1 に設定されています。レプリケーションスロットは、ファイルがコンシューマーによって外部的に使用されるまで WAL ファイルを保持します。例えば、pg_recvlogical、抽出、変換、ロード (ETL) ジョブ、または AWS DMS によって消費される可能性があります。

rds.logical_replication パラメータの値を 1 に設定した場合、AWS RDS は wal_levelmax_wal_sendersmax_replication_slots、および max_connections のパラメータを設定します。これらのパラメータを変更すると、WAL の生成が増加する可能性があります。rds.logical_replication パラメータは、論理スロットを使用している場合にのみ設定することをお勧めします。このパラメータが 1 に設定されていて、論理レプリケーションスロットが存在するが、レプリケーションスロットによって保持されている WAL ファイルのコンシューマーが存在しない場合は、トランザクションログのディスク使用量が増加します。これにより、ストレージの空き容量も常に減少します。

次のクエリを実行して、レプリケーションスロットの存在とサイズを確認します。

PostgreSQL v9:

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 v10 以降:

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

使用されていない (アクティブ状態が False) レプリケーションスロットを特定したら、次のクエリを実行してレプリケーションスロットを削除します。

psql=> SELECT pg_drop_replication_slot('Your_slotname_name');

注意:AWS DMS タスクがコンシューマーであり、不要になった場合は、タスクを削除してレプリケーションスロットを手動で削除します。

サンプル出力:

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

この例で、スロット名 xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d のアクティブ状態は False です。そのため、このスロットはアクティブに使用されておらず、スロットは 129 GB のトランザクションファイルに使用されています。

次のコマンドを実行してクエリを削除します。

psql=> SELECT pg_drop_replication_slot('xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

クロスリージョンリードレプリカのステータスを確認する

クロスリージョンリードレプリケーションを使用する場合、プライマリインスタンスに物理レプリケーションスロットが作成されます。クロスリージョンリードレプリカに障害が発生すると、プライマリ DB インスタンスのストレージ容量が影響を受ける可能性があります。これは、WAL ファイルがリードレプリカにレプリケートされないために発生します。CloudWatch メトリクス、最も古いレプリケーションスロットの遅れ、およびトランザクションログのディスク使用量を使用して、最も遅れているレプリカからどれだけ遅れているかを判断できます。また、WALデータに使用されているストレージの量も確認できます。

クロスリージョンリードレプリカのステータスを確認するには、クエリ pg_replication_slots を使用してください。詳細については、pg_replication_slots に関する PostgreSQL のドキュメントを参照してください。アクティブ状態が false として返された場合、そのスロットは現在レプリケーションに使用されていません。

psql=> SELECT * FROM pg_replication_slots;

ソースインスタンスで view pg_stat_replication を使用して、レプリケーションの統計を確認することもできます。詳細については、pg_stat_replication に関する PostgreSQL のドキュメントを参照してください。

実行されない行 (タプル) の肥大化または不適切な削除について確認する

通常の PostgreSQL 操作では、UPDATE によって削除されたか、古くなったタプルは、それらのテーブルから削除されません。マルチバージョン同時実行制御 (MVCC) 実装では、DELETE 操作が実行されても、行はデータファイルからすぐには削除されません。代わりに、ヘッダーの xmax フィールドを設定することによって、行が削除済みとしてマークされます。更新でも同様に、最初に行を削除対象としてマークし、次に挿入操作を実行します。これにより、異なるトランザクション間でロックを最小限に抑えながら、同時実行が可能になります。その結果、異なる行バージョンが MVCC プロセスの一部として保持されます。

実行されない行がクリーンアップされない場合、それらの行はデータファイルに残る可能性がありますが、どのトランザクションからも見えず、ディスク容量に影響します。テーブルに多くの DELETE および UPDATE 操作がある場合、実行されないタプルは大量のディスク容量を使用する可能性があります。これは PostgreSQL では「肥大化」と呼ばれることがあります。

VACUUM 操作は、実行されないタプルが使用していたストレージを解放して再利用できるようにしますが、空きストレージをファイルシステムに解放することはしません。VACUUM FULL を実行するとストレージがファイルシステムに解放されます。ただし、VACUUM FULL の実行中は、テーブルにアクセス排他ロックが保持されることに注意してください。この方法では、テーブルの新しいコピーを書き込み、操作が完了するまで古いコピーを解放しないため、追加のディスク容量も必要です。この方法は、テーブル内から大量のスペースを再利用する必要がある場合にのみ使用することをお勧めします。頻繁に更新されるテーブルに対して、定期的なバキューム操作または自動バキューム操作を実行することもお勧めします。詳細については、VACUUM に関する PostgreSQL のドキュメントを参照してください。

実行されないタプルの推定数を確認するには、pg_stat_all_tables ビューを使用してください。詳細については、pg_stat_all_tables ビューに関する PostgreSQL のドキュメントを参照してください。この例には、実行されないタプル (n_dead_tup) が 1999952 個あります。

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     | 2018-08-16 04:49:52.399546+00
last_analyze        | 2018-08-09 09:44:56.208889+00
last_autoanalyze    | 2018-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.    これらのクエリを実行して、使用されているサイズと実際のサイズを評価します。

# Size of the database occupied by files
psql=> SELECT pg_size_pretty(pg_database_size('DATABASE_NAME')); 

# Size of database retrieved by summing the objects (real size)
psql=> SELECT pg_size_pretty(SUM(pg_relation_size(oid))) FROM pg_class;

3.    結果をメモしてください。違いが大きい場合は、孤立したファイルがストレージ領域を使用している可能性があります。


この記事は役に立ちましたか?


請求に関するサポートまたは技術サポートが必要ですか?