スキップしてコンテンツを表示

Amazon RDS for PostgreSQL で "デバイスに空き領域がありません" や "DiskFull" というエラーが発生する理由を知りたいです。

所要時間3分
0

小規模の Amazon Relational Database Service (Amazon RDS) for PostgreSQL データベースを使用しています。その DB インスタンスの空きストレージ容量が減少しており、次のエラーが発生しています。 "エラーメッセージ: PG::DiskFull: ERROR: ファイル "base/16394/5139755" を拡張できませんでした。 デバイスに空き領域がありません。HINT: 空きディスク容量を確認してください。"

解決策

注: ワークロードが予測可能な場合は、インスタンスでストレージの自動スケーリングを有効化します。ストレージの自動スケーリングを使用すると、データベースの空き容量が少なくなったときに、Amazon RDS が自動的にストレージをスケーリングします。

ストレージ容量の監視には、Amazon CloudWatch メトリクス FreeStorageSpace を確認します。空きストレージ容量に関する CloudWatch アラームを設定し、スペースが減少し始めたときに通知を受け取るようにします。アラームを受信した場合は、Amazon RDS DB インスタンスのストレージを使用している次のリソースについて確認します。

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

DB インスタンスが予想以上にストレージを消費している場合は、次のトラブルシューティングアクションを実行してください。

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

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

過剰なログ記録を減らすには、DB パラメータグループのエラー報告パラメータとログ記録パラメータを変更します。この対応をとることで、ログファイルのサイズを削減できます。詳細については、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_files 列と temp_bytes 列は、集計された統計情報を収集します。Amazon RDS はこれらのカウンタを即時シャットダウン、サーバーのクラッシュ、ポイントインタイムリカバリ (PITR) が発生した後にのみリセットします。したがって、出力を確認するだけでなく、これらのファイルの数とサイズの増加を監視することがベストプラクティスです。

Amazon RDS は、ソート、ハッシュ、一時的なクエリ結果用の一時ファイルを作成します。一時テーブルまたはファイルの作成を追跡するには、すべての一時ファイル情報を記録するために、カスタムパラメータグループで log_temp_files0 に設定します。log_temp_files は、デフォルトでは -1 に設定されているため、Amazon RDS は一時ファイルを記録しません。log_temp_files を正の値に設定すると、Amazon RDS はそのキロバイト数以上のファイルのみをログに記録します。

クエリに EXPLAIN ANALYZE を実行し、ディスクのソートを確認します。ログ出力で、クエリによって作成される一時ファイルのサイズを確認します。詳細については、「work_mem を使用して PostgreSQL のソート操作を調整する」を参照してください。

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

TransactionLogsDiskUsage メトリクスを参考に、トランザクション WAL が使用しているディスク容量を確認します。トランザクションログのディスク使用量は、次の原因で増加する場合があります。

  • 追加の WA Lを生成する書き込みや更新による DB 負荷の増加
  • 同じ AWS リージョン内のレプリカでの、リードレプリカのストリーミングによる遅延、またはストレージフル状態のリードレプリカ
  • レプリケーションスロット

AWS Database Migration Service (AWS DMS) は、論理デコードの一環でレプリケーションスロットを作成する場合があります。論理レプリケーションでは、rds.logical_replication スロットパラメータは 1 に設定されています。レプリケーションスロットは、外部コンシューマーがファイルを使用するまで WAL ファイルを保持します。コンシューマーには、pg_recvlogical、抽出、変換、ロード (ETL) ジョブ、AWS DMS などがあります。

rds.logical_replication1 に設定した場合は、Amazon RDS により wal_levelmax_wal_sendersmax_replication_slotsmax_connections パラメータが設定されます。これらのパラメータを変更すると、WAL の生成が増加する可能性があります。rds.logical_replication パラメータは、論理スロットを使用する場合にのみ設定するのがベストプラクティスです。保持されている 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 ;

出力例:

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 slow のアクティブ状態は f です。このスロットはアクティブには使用されていませんが、129 GB のトランザクションファイルを使用しています。

使われていないスロットを削除するには、次のクエリを実行します。

psql=> SELECT pg_drop_replication_slot('YOUR_SLOTNAME');

注: _SLOTNAME を実際のスロット名に置き換えます。

出力例:

psql=> SELECT pg_drop_replication_slot('xc36ujql35djp_00013322_907c1e0a_9f8b_4c13_89ea_ef0ea1cf143d');

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

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

注: PostgreSQL 14.1 以降で実行されている場合のみ、同じリージョンのリードレプリカに次の解決策を使用できます。

クロスリージョンまたは同じリージョンのリードレプリケーションを使用している場合、Amazon RDS はプライマリインスタンスに物理レプリケーションスロットを作成します。リードレプリカの障害により、プライマリ DB インスタンスのストレージスペースが影響を受ける場合があります。この状況は、WAL ファイルがリードレプリカに複製されていない場合に発生します。OldestReplicationsSlotLag および TransactionLogsDiskUsage メトリクスを確認し、遅延が最も大きいレプリカの遅延の度合いを判断します。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 によりテーブルで不要になったりしたデッドロー (タプル) を削除することはありません。マルチバージョン同時実行制御 (MVCC) の実装では、DELETE 操作を実行しても、行はデータファイルからすぐには削除されません。代わりに、PostgreSQL はヘッダーに xmax フィールドを設定することで、その行を削除済みとしてマークします。更新では、最初に行を削除対象としてマークした後に、挿入操作を実行することで、異なるトランザクション間のロックを最小限に抑えて同時実行を実現します。その結果、PostgreSQL は MVCC プロセスの一環として複数の行バージョンを保持します。

クリーンアップされていないデッドローはデータファイルには残りますが、トランザクションからは不可視のままです。これらの行が原因で、ディスク容量の問題が起こる場合があります。テーブルに DELETE および UPDATE 操作が多数ある場合、デッドタプルが大量のディスク容量を消費する可能性があります (肥大化)。

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 でリードレプリカを操作する

自動監視ツール

コメントはありません

関連するコンテンツ