

# RDS for PostgreSQL で積極的なバキュームのブロック要因を特定して解決する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring"></a>

PostgreSQL でデータベースの正常な状態を維持するためにはバキューム処理が不可欠です。バキューム処理によって、ストレージの再利用が可能になり、[トランザクション ID の循環](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)に関する問題を回避できます。しかし、バキューム処理が目的どおりに動作しなくなることもあります。これにより、パフォーマンスの低下やストレージの肥大化が生じ、トランザクション ID の循環によって DB インスタンスの可用性にも影響する場合があります。したがって、データベースのパフォーマンスと可用性を最適化するには、これらの問題を特定して解決することが不可欠です。「[Understanding autovacuum in Amazon RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)」で自動バキュームの詳細について確認してください。

`postgres_get_av_diag()` 関数は、積極的なバキュームの進行を妨げたり遅らせたりしている問題を特定するのに役立ちます。推奨事項が提示され、問題が特定可能な場合はそれを解決するためのコマンドが、問題を特定できない場合は詳細な診断のためのガイダンスが得られます。積極的なバキュームのブロック要因は、経過時間が RDS の[適応型自動バキューム](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)のしきい値である 5 億トランザクション ID を超えた場合に報告されます。

**トランザクション ID の経過時間とは**

トランザクション ID の `age()` 関数は、データベース (`pg_database.datfrozenxid`) またはテーブル (`pg_class.relfrozenxid`) の最も古いフリーズしていないトランザクション ID 以降に発生したトランザクションの数を計算します。この値は、前回の積極的なバキューム操作以降のデータベースアクティビティを示し、今後の VACUUM プロセスのワークロードについての見通しを示します。

**積極的なバキュームとは**

積極的な VACUUM 操作では、通常の VACUUM で省略されるページも含め、テーブル内のすべてのページが包括的にスキャンされます。この徹底的なスキャンは、最大経過時間に近づいているトランザクション ID を「フリーズ」することを目指しており、[トランザクション ID の循環](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)と呼ばれる状況を効果的に防止します。

`postgres_get_av_diag()` で報告されるブロック要因は、5 億トランザクション以上古いものとなります。

**Topics**
+ [RDS for PostgreSQL に自動バキュームのモニタリングツールと診断ツールをインストールする](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)
+ [RDS for PostgreSQL の postgres\$1get\$1av\$1diag() の関数](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.md)
+ [RDS for PostgreSQL での識別可能なバキュームブロック要因の解決](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md)
+ [RDS for PostgreSQL での識別不能なバキュームブロック要因の解決](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers.md)
+ [RDS for PostgreSQL でバキュームのパフォーマンスに関する問題を解決する](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md)
+ [RDS for PostgreSQL の NOTICE メッセージの説明](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

# RDS for PostgreSQL に自動バキュームのモニタリングツールと診断ツールをインストールする
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation"></a>

`postgres_get_av_diag()` 関数は現在、次の RDS for PostgreSQL バージョンで使用できます。
+ 17.2 以降の 17 バージョン
+ 16.7 以降の 16 バージョン
+ 15.11 以降の 15 バージョン
+ 14.16 以降の 14 バージョン
+ 13.19 以降の 13 バージョン

 `postgres_get_av_diag()` を使用するには、`rds_tools` 拡張機能を作成します。

```
postgres=> CREATE EXTENSION rds_tools ;
CREATE EXTENSION
```

拡張機能がインストールされていることを確認します。

```
postgres=> \dx rds_tools
             List of installed extensions
   Name    | Version |  Schema   |                    Description
 ----------+---------+-----------+----------------------------------------------------------
 rds_tools |   1.8   | rds_tools | miscellaneous administrative functions for RDS PostgreSQL
 1 row
```

関数が作成されていることを確認します。

```
postgres=> SELECT
    proname function_name,
    pronamespace::regnamespace function_schema,
    proowner::regrole function_owner
FROM
    pg_proc
WHERE
    proname = 'postgres_get_av_diag';
    function_name     | function_schema | function_owner
----------------------+-----------------+----------------
 postgres_get_av_diag | rds_tools       | rds_superuser
(1 row)
```

# RDS for PostgreSQL の postgres\$1get\$1av\$1diag() の関数
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions"></a>

`postgres_get_av_diag()` 関数は、RDS for PostgreSQL データベースで妨害または遅延が生じている自動バキュームプロセスに関する診断情報を取得します。正確な結果を得るには、最も古いトランザクション ID を持つデータベースでクエリを実行する必要があります。最も古いトランザクション ID を持つデータベースを使用する方法の詳細については、「[トランザクション ID の経過時間が最も古いデータベースに接続していない](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)」を参照してください。

```
SELECT
    blocker,
    DATABASE,
    blocker_identifier,
    wait_event,
    TO_CHAR(autovacuum_lagging_by, 'FM9,999,999,999') AS autovacuum_lagging_by,
    suggestion,
    suggested_action
FROM (
    SELECT
        *
    FROM
        rds_tools.postgres_get_av_diag ()
    ORDER BY
        autovacuum_lagging_by DESC) q;
```

`postgres_get_av_diag()` 関数は次の情報を含むテーブルを返します。

**blocker**  
バキュームをブロックしているデータベースアクティビティのカテゴリを指定します。  
+ [アクティブなステートメント](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [トランザクションでのアイドル状態](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [準備済みトランザクション](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [論理レプリケーションスロット](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [物理レプリケーションスロットを使用するリードレプリカ](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [ストリーミングレプリケーションを使用するリードレプリカ](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [一時テーブル](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

**database**  
該当しサポートされている場合にデータベースの名前を指定します。これは、アクティビティが進行中で、自動バキュームをブロックしている、またはこれからブロックするデータベースです。これは、接続してアクションを実行する必要があるデータベースです。

**blocker\$1identifier**  
自動バキュームをブロックしている、またはこれからブロックするアクティビティの識別子を指定します。識別子は、プロセス ID に SQL ステートメント、準備済みトランザクション、リードレプリカの IP アドレス、および論理または物理レプリケーションスロットの名前を加えたものとなります。

**wait\$1event**  
ブロックしているセッションの[待機イベント](PostgreSQL.Tuning.md)を指定し、次のブロック要因に適用されます。  
+ アクティブなステートメント
+ トランザクションでのアイドル状態

**autovacum\$1lagging\$1by**  
バックログ作業で自動バキュームが停滞しているトランザクションの数をカテゴリごとに指定します。

**suggestion**  
ブロック要因を解決するための推奨事項を指定します。これらの手順には、アクティビティが存在するデータベースの名前 (該当する場合)、セッションのプロセス ID (PID)(該当する場合)、および実行するアクションが含まれます。

**suggested\$1action**  
ブロック要因を解決するために実行する必要があるアクションを提案します。

# RDS for PostgreSQL での識別可能なバキュームブロック要因の解決
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers"></a>

自動バキュームは積極的なバキュームを実行し、トランザクション ID の経過時間が RDS インスタンスの `autovacuum_freeze_max_age` パラメータで指定されたしきい値に達しないようにします。この経過時間は、Amazon CloudWatch メトリクス `MaximumUsedTransactionIDs` を使用して追跡できます。

Amazon RDS インスタンスの `autovacuum_freeze_max_age` の設定 (デフォルトは 2 億トランザクション ID) を確認するには、次のクエリを使用します。

```
SELECT
    TO_CHAR(setting::bigint, 'FM9,999,999,999') autovacuum_freeze_max_age
FROM
    pg_settings
WHERE
    name = 'autovacuum_freeze_max_age';
```

`postgres_get_av_diag()` では、経過時間が Amazon RDS の[適応型自動バキューム](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)のしきい値である 5 億トランザクション ID を超えた場合にのみ、積極的なバキュームのブロック要因をチェックすることに注意してください。`postgres_get_av_diag()` で検出されるブロック要因は、5 億トランザクション以上古いものとなります。

`postgres_get_av_diag()` 関数は、次のタイプのブロック要因を識別します。

**Topics**
+ [アクティブなステートメント](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [トランザクションでのアイドル状態](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [準備済みトランザクション](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [論理レプリケーションスロット](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [リードレプリカ](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [一時テーブル](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

## アクティブなステートメント
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement"></a>

PostgreSQL において、アクティブなステートメントとは、データベースによって現在実行されている SQL ステートメントです。これには、クエリ、トランザクション、または進行中のすべてのオペレーションが含まれます。`pg_stat_activity` を使ってモニタリングする場合、状態列には、対応する PID を持つプロセスがアクティブであることが示されます。

`postgres_get_av_diag()` 関数がアクティブなステートメントであるステートメントを識別すると、次のような出力を表示します。

```
blocker               | Active statement
database              | my_database
blocker_identifier    | SELECT pg_sleep(20000);
wait_event            | Timeout:PgSleep
autovacuum_lagging_by | 568,600,871
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (29621);"}
```

**推奨されるアクション**

`suggestion` 列のガイダンスに従って、ユーザーはアクティブなステートメントが存在するデータベースに接続できます。`suggested_action` 列で指定されているように、セッションを終了するオプションを慎重に検討することが推奨されます。終了しても安全な場合は、`pg_terminate_backend()` 関数を使用してセッションを終了できます。このアクションは、管理者 (RDS マスターアカウントなど) または必要な `pg_terminate_backend()` 権限を持つユーザーが実行できます。

**警告**  
終了したセッションは、行われた変更を元に戻します (`ROLLBACK`)。要件に応じて、ステートメントを再度実行できます。ただし、自動バキュームプロセスが積極的なバキューム操作を完了した後にのみ実行することをお勧めします。

## トランザクションでのアイドル状態
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction"></a>

トランザクションステートメントのアイドル状態とは、明示的なトランザクションを開き (`BEGIN` ステートメントの発行など)、何らかの作業を実行したセッションで、クライアントがさらに作業を渡すか、`COMMIT`、`ROLLBACK`、`END` (暗黙的な `COMMIT` になります) を発行してトランザクションの終了を通知するのを待っているセッションを指します。

`postgres_get_av_diag()` 関数が `idle in transaction` ステートメントをブロック要因として識別すると、次のような出力を表示します。

```
blocker               | idle in transaction
database              | my_database
blocker_identifier    | INSERT INTO tt SELECT * FROM tt;
wait_event            | Client:ClientRead
autovacuum_lagging_by | 1,237,201,759
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (28438);"}
```

**推奨されるアクション**

`suggestion` 列に示されているように、トランザクションセッションでのアイドル状態が存在するデータベースに接続し、`pg_terminate_backend()` 関数を使用してセッションを終了できます。ユーザーは、管理者 (RDS マスターアカウント) ユーザーでも、 `pg_terminate_backend()` 権限を持つユーザーでもかまいません。

**警告**  
終了したセッションは、行われた変更を元に戻します (`ROLLBACK`)。要件に応じて、ステートメントを再度実行できます。ただし、自動バキュームプロセスが積極的なバキューム操作を完了した後にのみ実行することをお勧めします。

## 準備済みトランザクション
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction"></a>

PostgreSQL では、[準備済みトランザクション](https://www.postgresql.org/docs/current/sql-prepare-transaction.html)と呼ばれる 2 相コミット戦略の一部であるトランザクションを使用できます。これらは、`max_prepared_transactions` パラメータをゼロ以外の値に設定することで有効になります。準備済みトランザクションは、データベースのクラッシュ、再起動、またはクライアントの切断後も、トランザクションが持続し、引き続き使用できるように設計されています。通常のトランザクションと同様に、トランザクション ID が割り当てられ、自動バキュームに影響を与える場合があります。準備状態のままにすると、自動バキュームはフリーズを実行できず、トランザクション ID の循環につながる可能性があります。

トランザクションマネージャによって解決されることなく無期限に準備状態となったトランザクションは、孤立した準備済みトランザクションになります。これを修正する唯一の方法は、`COMMIT PREPARED` コマンドまたは `ROLLBACK PREPARED` コマンドを使用してトランザクションをコミットするかロールバックすることです。

**注記**  
準備済みトランザクションで作成されたバックアップには、復元後もそのトランザクションが含まれることに注意してください。このようなトランザクションを見つけて閉じる方法については、以下の情報を参照してください。

`postgres_get_av_diag()` 関数が準備済みトランザクションをブロック要因として識別すると、次の出力を表示します。

```
blocker               | Prepared transaction
database              | my_database
blocker_identifier    | myptx
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database" and consider either COMMIT or ROLLBACK the prepared transaction using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"COMMIT PREPARED 'myptx';",[OR],"ROLLBACK PREPARED 'myptx';"}
```

**推奨されるアクション**

suggestion 列で説明されているように、準備済みトランザクションがあるデータベースに接続します。`suggested_action` 列に基づいて、`COMMIT` と `ROLLBACK` のどちらを実行するかを慎重に検討し、適切なアクションを選択します。

準備済みトランザクション全般をモニタリングするために、PostgreSQL には `pg_prepared_xacts` というカタログビューが用意されています。次のクエリを使用して、準備済みトランザクションを検索できます。

```
SELECT
    gid,
    prepared,
    owner,
    database,
    transaction AS oldest_xmin
FROM
    pg_prepared_xacts
ORDER BY
    age(transaction) DESC;
```

## 論理レプリケーションスロット
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot"></a>

レプリケーションスロットの目的は、ターゲットサーバーにレプリケートされるまで、未使用の変更を保持することです。詳細については、PostgreSQL の「[Logical replication](https://www.postgresql.org/docs/current/logical-replication.html)」を参照してください。

論理レプリケーションスロットには 2 つのタイプがあります。

**非アクティブな論理レプリケーションスロット**

レプリケーションが終了すると、未使用のトランザクションログは削除されず、レプリケーションスロットは非アクティブになります。非アクティブな論理レプリケーションスロットは、現在、サブスクライバーによって使用されていませんが、サーバーには残るため、WAL ファイルが保持され、古いトランザクションログが削除されなくなります。システムは LSN 情報が上書きされないよう保持する必要があるため、ディスク使用量が増加し、具体的には、自動バキュームで内部カタログテーブルをクリーンアップできなくなる可能性があります。放置するとカタログの肥大化とパフォーマンスの低下を招き、循環バキュームのリスクが増大して、トランザクションのダウンタイムが発生する可能性があります。

**アクティブだが遅い論理レプリケーションスロット**

論理レプリケーションのパフォーマンスの低下により、カタログのデッドタプルの削除が遅れることがあります。このレプリケーションの遅延により、`catalog_xmin` の更新が遅れ、カタログの肥大化や循環バキュームが発生する可能性があります。

`postgres_get_av_diag()` 関数が論理レプリケーションスロットをブロック要因として検出すると、次のような出力を表示します。

```
blocker               | Logical replication slot
database              | my_database
blocker_identifier    | slot1
wait_event            | Not applicable
autovacuum_lagging_by | 1,940,103,068
suggestion            | Ensure replication is active and resolve any lag for the slot if active. If inactive, consider dropping it using the command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_drop_replication_slot('slot1') FROM pg_replication_slots WHERE active = 'f';"}
```

**推奨されるアクション**

この問題を解決するには、レプリケーション設定で、適用プロセスを終了している可能性のあるターゲットスキーマまたはデータの問題を確認します。最も一般的な理由を次に示します。
+ 列の欠落
+ 互換性のないデータ型
+ データの不一致
+ データの欠落

問題がインフラストラクチャの問題に関連している場合
+ ネットワークの問題 - [互換性のないネットワーク状態にある Amazon RDS DB の問題を解決するにはどうすればよいですか?](https://repost.aws/knowledge-center/rds-incompatible-network)
+ データベースまたは DB インスタンスが、次の理由により使用できない
  + レプリカインスタンスのストレージが不足している - 「[Amazon RDS DB インスタンスのストレージが不足したときに発生する問題を解決する方法を教えてください](https://repost.aws/knowledge-center/rds-out-of-storage)」を参照して、ストレージの追加について確認してください。
  + 互換性のないパラメータ - 「[互換性のないパラメータステータスのままになっている Amazon RDS DB インスタンスを修正するにはどうすればよいですか?](https://repost.aws/knowledge-center/rds-incompatible-parameters)」を参照して、問題を解決する方法の詳細を確認してください。

インスタンスが AWS ネットワーク外または AWS EC2 上にある場合は、可用性またはインフラストラクチャ関連の問題の解決方法について管理者に問い合わせてください。

**非アクティブなスロットの削除**

**警告**  
注意: レプリケーションスロットを削除する前に、レプリケーションが進行中ではないこと、レプリケーションスロットが非アクティブで回復不可能な状態であることを慎重に確認してください。スロットを途中で削除すると、レプリケーションが中断されたり、データが失われたりする可能性があります。

レプリケーションスロットが不要になったことを確認したら、削除して自動バキュームを続行できるようにします。条件 `active = 'f'` を指定することで、非アクティブなスロットのみが削除されます。

```
SELECT pg_drop_replication_slot('slot1') WHERE active ='f'
```

## リードレプリカ
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas"></a>

[Amazon RDS リードレプリカ](USER_PostgreSQL.Replication.ReadReplicas.md)で `hot_standby_feedback` 設定が有効になっている場合、リードレプリカで実行されているクエリで引き続き必要になる可能性のあるデッド行は、プライマリデータベースの自動バキュームで削除されません。これは、レプリケーションスロットを使用して管理されているかどうかにかかわらず、すべてのタイプの物理リードレプリカに影響します。スタンバイレプリカで実行されているクエリでは、[クエリの競合](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT)やキャンセルを防ぐために、これらの行をプライマリで利用できる状態に保つ必要があるため、こうした動作が必要になります。

**物理レプリケーションスロットを使用するリードレプリカ**  
物理レプリケーションスロットを使用するリードレプリカでは、RDS for PostgreSQL でのレプリケーションの信頼性と安定性が大幅に強化されます。これらのスロットにより、プライマリデータベースはレプリカが処理するまで重要なログ先行書き込みファイルを保持し、ネットワークの中断中もデータ整合性を維持できます。

RDS for PostgreSQL バージョン 14 以降、すべてのレプリカでレプリケーションスロットが使用されます。以前のバージョンでは、クロスリージョンレプリカのみでレプリケーションスロットが使用されていました。

`postgres_get_av_diag()` 関数が物理レプリケーションスロットを使用するリードレプリカをブロック要因として検出すると、次のような出力を表示します。

```
blocker               | Read replica with physical replication slot
database              |
blocker_identifier    | rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxxx
wait_event            | Not applicable
autovacuum_lagging_by | 554,080,689
suggestion            | Run the following query on the replica "rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxx" to find the long running query:                           
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;                                                       
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                 +                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;","                                                                                 +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                   +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Delete the read replica if not needed"}
```

**ストリーミングレプリケーションを使用するリードレプリカ**  
Amazon RDS では、バージョン 13 までの古いバージョンで、物理レプリケーションスロットを使用せずにリードレプリカを設定できます。このアプローチでは、プライマリが WAL ファイルをより積極的にリサイクルできるようにすることでオーバーヘッドを軽減します。これは、ディスク容量が制限された環境においてメリットがあり、ときどき発生するレプリケーションの遅延も許容できます。ただし、スロットを使用しない場合、WAL ファイルが欠落しないように、スタンバイは同期したままにする必要があります。Amazon RDS は、レプリカが遅れをとった場合にアーカイブされた WAL ファイルを使用して遅れを解消しますが、このプロセスには慎重なモニタリングが必要となり、時間がかかることがあります。

`postgres_get_av_diag()` 関数がストリーミングリードレプリカをブロック要因として検出すると、次のような出力を表示します。

```
blocker               | Read replica with streaming replication slot
database              | Not applicable
blocker_identifier    | xx.x.x.xxx/xx
wait_event            | Not applicable
autovacuum_lagging_by | 610,146,760
suggestion            | Run the following query on the replica "xx.x.x.xxx" to find the long running query:                                                                                                                                                         +
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;                                                                                                                                                     +
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                       +
                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;","                                                                                                                        +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                                                          +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Delete the read replica if not needed"}
```

**推奨されるアクション**

`suggested_action` 列で推奨されているように、以下のオプションを慎重に検討して自動バキュームのブロックを解除します。
+ **クエリを終了する** – suggestion 列のガイダンスに従って、suggested\$1action 列で指定されているようにリードレプリカに接続できます。セッションを終了するオプションは慎重に検討することをお勧めします。終了しても安全であると判断した場合は、`pg_terminate_backend()` 関数を使用してセッションを終了できます。このアクションは、管理者 (RDS マスターアカウントなど) または必要な pg\$1terminate\$1backend() 権限を持つユーザーが実行できます。

  リードレプリカで次の SQL コマンドを実行すると、プライマリのバキュームによる古い行のクリーンアップを妨げているクエリを終了できます。`backend_xmin` の値は、関数の出力で報告されます。

  ```
  SELECT
      pg_terminate_backend(pid)
  FROM
      pg_catalog.pg_stat_activity
  WHERE
      backend_xmin::text::bigint = backend_xmin;
  ```
+ **ホットスタンバイフィードバックを無効にする** – `hot_standby_feedback` パラメータがバキュームの大幅な遅延の原因となっている場合は、これを無効にすることを検討します。

  `hot_standby_feedback` パラメータを使用すると、リードレプリカはクエリアクティビティについてプライマリに通知し、プライマリがスタンバイで使用されているテーブルや行をバキューム処理できないようにします。これによりスタンバイでのクエリの安定性が確保されますが、プライマリでのバキューム処理が大幅に遅延する可能性があります。この機能を無効にすると、プライマリはスタンバイが追いつくのを待たずにバキューム処理を進めることができます。ただし、プライマリによってバキューム処理された行にアクセスしようとすると、スタンバイでクエリのキャンセルや失敗が発生する可能性があります。
+ **不要になったリードレプリカを削除する** – リードレプリカが不要になった場合は、削除できます。これにより、関連するレプリケーションオーバーヘッドが解消され、プライマリがレプリカによって妨げられることなくトランザクションログをリサイクルできるようになります。

## 一時テーブル
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables"></a>

`TEMPORARY` キーワードを使用して作成された[一時テーブル](https://www.postgresql.org/docs/current/sql-createtable.html)は、pg\$1temp\$1xxx などの一時スキーマにあり、それらを作成したセッションのみがアクセスできます。一時テーブルは、セッションが終了すると削除されます。ただし、このようなテーブルは PostgreSQL の自動バキュームプロセスには表示されず、テーブルを作成したセッションによって手動でバキューム処理する必要があります。別のセッションから一時テーブルのバキューム処理を試みても効果はありません。

異常な状況下では、テーブルを所有するアクティブなセッションがない状態で一時テーブルが存在します。致命的なクラッシュ、ネットワークの問題、または同様のイベントが原因でテーブルを所有するセッションが予期せず終了した場合、一時テーブルはクリーンアップされず、「孤立した」テーブルとして残される可能性があります。PostgreSQL 自動バキュームプロセスで孤立した一時テーブルが検出されると、次のメッセージがログに記録されます。

```
LOG: autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"
```

`postgres_get_av_diag()` 関数が一時テーブルをブロック要因として識別すると、次のような出力を表示します。この関数で一時テーブルに関連する出力を正しく表示するには、それらのテーブルが存在するのと同じデータベース内で関数を実行する必要があります。

```
blocker               | Temporary table
database              | my_database
blocker_identifier    | pg_temp_14.ttemp
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database". Review carefully, you may consider dropping temporary table using command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"DROP TABLE ttemp;"}
```

**推奨されるアクション**

出力の `suggestion` 列に示されている手順に従って、自動バキュームの実行を妨げている一時テーブルを特定して削除します。次のコマンドを使用して、`postgres_get_av_diag()` で報告された一時テーブルを削除します。`postgres_get_av_diag()` 関数で提示された出力に基づいてテーブル名を置き換えます。

```
DROP TABLE my_temp_schema.my_temp_table;
```

次のクエリを使用して、一時テーブルを識別できます。

```
SELECT
    oid,
    relname,
    relnamespace::regnamespace,
    age(relfrozenxid)
FROM
    pg_class
WHERE
relpersistence = 't'
ORDER BY
    age(relfrozenxid) DESC;
```

# RDS for PostgreSQL での識別不能なバキュームブロック要因の解決
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers"></a>

このセクションでは、バキューム処理の進行を妨げる可能性のあるその他の理由について説明します。以下の問題は、現在、`postgres_get_av_diag()` 関数によって直接識別できません。

**Topics**
+ [無効なページ](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)
+ [インデックスの不整合](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency)
+ [トランザクションレートが極めて高い](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate)

## 無効なページ
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages"></a>

無効なページエラーは、PostgreSQL がページへのアクセス中にページのチェックサムの不一致を検出した場合に発生します。コンテンツが読み取れないため、自動バキュームでタプルがフリーズされません。これにより、クリーンアッププロセスが実質的に停止します。次のエラーが PostgreSQL の ログに書き込まれます。

```
WARNING:  page verification failed, calculated checksum YYYYY but expected XXXX
ERROR:  invalid page in block ZZZZZ of relation base/XXXXX/XXXXX
CONTEXT:  automatic vacuum of table myschema.mytable
```

**オブジェクトタイプを判断する**

```
ERROR: invalid page in block 4305910 of relation base/16403/186752608 
WARNING: page verification failed, calculated checksum 50065 but expected 60033
```

エラーメッセージのパス `base/16403/186752608` は、次の情報を提供しています。
+ 「base」は PostgreSQL データディレクトリのディレクトリ名です。
+ 「16403」はデータベース OID であり、`pg_database` システムカタログで検索できます。
+ 「186752608」は `relfilenode` であり、`pg_class` システムカタログでスキーマとオブジェクト名を検索するために使用できます。

影響を受けるデータベースで次のクエリの出力をチェックすることで、オブジェクトタイプを判断できます。次のクエリは、oid: 186752608 のオブジェクト情報を取得します。OID を、発生したエラーに関連する OID に置き換えます。

```
SELECT
    relname AS object_name,
    relkind AS object_type,
    nspname AS schema_name
FROM
    pg_class c
    JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
    c.oid = 186752608;
```

詳細については、PostgreSQL のドキュメント「[https://www.postgresql.org/docs/current/catalog-pg-class.html](https://www.postgresql.org/docs/current/catalog-pg-class.html)」で、`pg_class` の `relkind` 列で示されるサポート対象のすべてのオブジェクトタイプを参照してください。

**ガイダンス**

この問題の最も効果的な解決策は、特定の Amazon RDS インスタンスの設定と、整合性のないページの影響を受けるデータの種類によって異なります。

**オブジェクトタイプがインデックスの場合**

インデックスを再構築することをお勧めします。
+ **`CONCURRENTLY` オプションの使用** – PostgreSQL バージョン 12 より前のバージョンでは、インデックスを再構築するには、排他的テーブルロックによってテーブルへのアクセスを制限する必要がありました。PostgreSQL バージョン 12 以降のバージョンでは、`CONCURRENTLY` オプションにより行レベルのロックが可能になり、テーブルの可用性が大幅に向上しています。コマンドは以下のとおりです。

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  `CONCURRENTLY` はそれほど破壊的ではありませんが、ビジー状態のテーブルでは時間がかかる場合があります。可能であれば、トラフィックが少ない時間帯にインデックスを構築することを検討してください。

  詳細については、PostgreSQL ドキュメントの「[REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)」を参照してください。
+ **`INDEX_CLEANUP FALSE` オプションの使用** – インデックスが大きく、完了までにかなりの時間がかかると予想される場合は、インデックスを除外しながら手動 `VACUUM FREEZE` を実行して自動バキュームのブロックを解除できます。この機能は PostgreSQL バージョン 12 以降で使用できます。

  インデックスを無視すると、整合性のないインデックスのバキュームプロセスを省略して、循環の問題を軽減できます。ただし、無効なページの根本的な問題は解決されません。無効なページの問題に完全に対処し、これを解決するには、インデックスを再構築する必要があります。

**オブジェクトタイプがマテリアライズドビューの場合**

マテリアライズドビューで無効なページエラーが発生した場合は、影響を受けるデータベースにログインし、更新して無効なページを解決します。

マテリアライズドビューを更新します。

```
REFRESH MATERIALIZED VIEW schema_name.materialized_view_name;
```

更新に失敗した場合は、再作成を試みます。

```
DROP MATERIALIZED VIEW schema_name.materialized_view_name;
CREATE MATERIALIZED VIEW schema_name.materialized_view_name AS query;
```

マテリアライズドビューを更新または再作成すると、基盤となるテーブルデータに影響を与えずにマテリアライズドビューが復元されます。

**他のすべてのオブジェクトタイプの場合**

他のすべてのオブジェクトタイプについては、AWS サポートに問い合わせてください。

## インデックスの不整合
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency"></a>

論理的に整合性のないインデックスによって、自動バキュームの進行が妨げられる場合があります。次のエラーまたは同様のエラーは、インデックスのバキュームフェーズ中、または SQL ステートメントによってインデックスがアクセスされるときにログに記録されます。

```
ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
```

```
ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX
CONTEXT:  while vacuuming index index_name of relation schema.table
```

**ガイダンス**

手動 `VACUUM FREEZE` で `INDEX_CLEANUP` を使用してインデックスを再構築するか、インデックスを省略します。インデックスを再構築する方法の詳細については、「[オブジェクトタイプがインデックスの場合](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)」を参照してください。
+ **CONCURRENTLY オプションの使用** – PostgreSQL バージョン 12 より前のバージョンでは、インデックスを再構築するには、排他的テーブルロックによってテーブルへのアクセスを制限する必要がありました。PostgreSQL バージョン 12 以降のバージョンでは、CONCURRENTLY オプションにより行レベルのロックが可能になり、テーブルの可用性が大幅に向上しています。コマンドは以下のとおりです。

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  CONCURRENTLY はそれほど破壊的ではありませんが、ビジー状態のテーブルでは時間がかかる場合があります。可能であれば、トラフィックが少ない時間帯にインデックスを構築することを検討してください。詳細については、*PostgreSQL* ドキュメントの「[REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)」を参照してください。
+ **INDEX\$1CLEANUP FALSE オプションの使用** – インデックスが大きく、完了までにかなりの時間がかかると予想される場合は、インデックスを除外しながら手動 VACUUM FREEZE を実行して自動バキュームのブロックを解除できます。この機能は PostgreSQL バージョン 12 以降で使用できます。

  インデックスを無視すると、整合性のないインデックスのバキュームプロセスを省略して、循環の問題を軽減できます。ただし、無効なページの根本的な問題は解決されません。無効なページの問題に完全に対処し、これを解決するには、インデックスを再構築する必要があります。

## トランザクションレートが極めて高い
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate"></a>

PostgreSQL では、トランザクションレートが高いと自動バキュームのパフォーマンスに大きな影響を与え、デッドタプルのクリーンアップが遅くなり、トランザクション ID の循環のリスクが高まります。トランザクションレートは、2 つの期間 (通常は 1 秒ごと) の `max(age(datfrozenxid))` の差を測定することでモニタリングできます。さらに、RDS Performance Insights の次のカウンターメトリクスを使用して、トランザクションの合計数であるトランザクションレート (xact\$1commit と xact\$1rollback の合計) を測定できます。


|  Counter  |  タイプ  |  単位  |  メトリクス  | 
| --- | --- | --- | --- | 
|  xact\$1commit  |  トランザクション  |  1 秒あたりのコミット数  |  db.Transactions.xact\$1commit  | 
|  xact\$1rollback  |  トランザクション  |  1 秒あたりのロールバック数  |  db.Transactions.xact\$1rollback  | 

急激な増加は、トランザクション負荷が高いことを示しており、自動バキュームが過負荷になり、肥大化、ロック競合、および潜在的なパフォーマンスの問題が発生する可能性があります。これにより、以下のような点で自動バキュームプロセスに悪影響が及ぶ可能性があります。
+ **テーブルアクティビティ:** バキューム処理されている特定のテーブルで大量のトランザクションが発生し、遅延が発生する可能性があります。
+ **システムリソース:** システム全体が過負荷になっている可能性があるため、自動バキュームが効率的に機能するために必要なリソースにアクセスすることが困難になります。

自動バキュームをより効果的に動作させ、遅延なくタスクに対処するために、次の戦略を検討してください。

1. 可能であれば、トランザクションレートを下げます。可能な場合は、類似したトランザクションをバッチ処理またはグループ化することを検討してください。

1. オフピークの時間帯は、毎晩、毎週、または隔週の手動 `VACUUM FREEZE` オペレーションで頻繁に更新されるテーブルをターゲットにします。

1. インスタンスクラスをスケールアップして、大量のトランザクションと自動バキュームを処理するためにより多くのシステムリソースを割り当てることを検討してください。

# RDS for PostgreSQL でバキュームのパフォーマンスに関する問題を解決する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance"></a>

このセクションでは、バキュームのパフォーマンスの低下を招く要因と、それらの問題に対処する方法について説明します。

**Topics**
+ [大規模なインデックスのバキューム処理](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes)
+ [バキューム処理対象のテーブルまたはデータベースが多すぎる](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables)
+ [(循環を防ぐための) 積極的なバキューム処理が実行されている](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

## 大規模なインデックスのバキューム処理
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes"></a>

VACUUM は、初期化、ヒープスキャン、インデックスとヒープバキューム、インデックスクリーンアップ、ヒープ切り捨て、最終クリーンアップのシーケンシャルフェーズで動作します。ヒープスキャン中、プロセスはページを除外し、デフラグしてフリーズします。ヒープスキャンが完了すると、VACUUM はインデックスをクリーンアップし、空のページがオペレーティングシステムに返されて、空き領域マップのバキューム処理や統計の更新などの最終的なクリーンアップタスクを実行します。

`maintenance_work_mem` (または `autovacuum_work_mem`) がインデックスの処理に不十分な場合は、インデックスのバキューム処理に複数のパスが必要になることがあります。PostgreSQL 16 以前では、デッドタプル ID を保存するために 1 GB のメモリ制限があり、大きなインデックスでは、多くの場合複数のパスが必要となっていました。PostgreSQL 17 では、単一の割り当て配列を使用する代わりにメモリを動的に割り当てる `TidStore` が導入されています。これにより、1 GB の制約がなくなり、メモリをより効率的に使用でき、インデックスごとに複数のインデックススキャンを行う必要が軽減されます。

使用可能なメモリがインデックス処理全体を一度に処理できない場合、大きなインデックスには PostgreSQL 17 で複数のパスが必要になることがあります。通常、大きなインデックスには、複数のパスを必要とするデッドタプルが多く含まれます。

**低速バキュームオペレーションの検出**

`postgres_get_av_diag()` 関数は、メモリ不足が原因でバキューム操作の実行が遅いタイミングを検出できます。この関数の詳細については、「[RDS for PostgreSQL に自動バキュームのモニタリングツールと診断ツールをインストールする](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)」を参照してください。

この `postgres_get_av_diag()` 関数は、使用可能なメモリが 1 回のパスでインデックスのバキューム処理を完了するのに十分でない場合、次の通知を発行します。

**`rds_tools` 1.8**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).
```

**`rds_tools` 1.9**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see 
        [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)
        .
```

**注記**  
`postgres_get_av_diag()` 関数では、`pg_stat_all_tables.n_dead_tup` を使用してインデックスのバキューム処理に必要なメモリ量を推定します。

`postgres_get_av_diag()` 関数が、`autovacuum_work_mem` が不十分なために複数のインデックススキャンを必要とするスローバキュームオペレーションを特定すると、次のメッセージが生成されます。

```
NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html).
```

**ガイダンス**

手動 `VACUUM FREEZE` を使用して次の回避策を適用し、テーブルのフリーズにかかる時間を短縮できます。

**バキューム処理のためのメモリを増やす**

`postgres_get_av_diag()` 関数で提案されているように、インスタンスレベルで潜在的なメモリの制約に対応するために、`autovacuum_work_mem` パラメータを増やすことをお勧めします。`autovacuum_work_mem` は動的パラメータですが、新しいメモリ設定を有効にするには、自動バキュームデーモンがワーカーを再起動する必要があることに注意してください。これを行うには、以下の手順を使用します。

1. 新しい設定が指定されていることを確認します。

1. 自動バキュームを現在実行しているプロセスを終了します。

このアプローチにより、調整されたメモリ割り当てが新しい自動バキューム操作に適用されます。

より迅速な結果を得るには、セッション内で `maintenance_work_mem` 設定を増やし、手動で `VACUUM FREEZE` 操作を実行することを検討してください。

```
SET maintenance_work_mem TO '1GB';
VACUUM FREEZE VERBOSE table_name;
```

Amazon RDS を使用していて、`maintenance_work_mem` または `autovacuum_work_mem` のより高い値をサポートするために追加のメモリが必要であると判断した場合は、より多くのメモリを持つインスタンスクラスにアップグレードすることを検討してください。これにより、手動バキューム操作と自動バキューム操作の両方を強化するために必要なリソースが提供され、バキューム処理とデータベースの全体的なパフォーマンスが向上します。

**INDEX\$1CLEANUP を無効にする**

PostgreSQL バージョン 12 以降の手動 `VACUUM` ではインデックスのクリーンアップフェーズを省略できますが、PostgreSQL バージョン 14 以降の緊急自動バキュームでは、[https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE) パラメータに基づいてこのフェーズが自動的に行われます。

**警告**  
インデックスのクリーンアップを省略すると、インデックスが肥大化し、クエリのパフォーマンスに悪影響を及ぼす可能性があります。これを軽減するには、メンテナンスウィンドウで、影響を受けるインデックスに対してインデックスの再作成またはバキューム処理を行うことを検討してください。

大きなインデックスの処理に関するその他のガイダンスについては、「[大きなインデックスを使った autovacuum の管理](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)」のドキュメントを参照してください。

**インデックスの並列バキューム処理**

PostgreSQL 13 以降では、手動 `VACUUM` を使用して、各インデックスに 1 つのバキュームワーカープロセスを割り当て、デフォルトで複数のインデックスのバキューム処理とクリーンアップを並列して行うことができます。ただし、バキューム操作が並列実行の対象となるかどうかを PostgreSQL が判断するには、特定の基準を満たす必要があります。
+ 少なくとも 2 つのインデックスが必要です。
+ `max_parallel_maintenance_workers` パラメータを 2 以上に設定する必要があります。
+ インデックスサイズが `min_parallel_index_scan_size` の制限 (デフォルトは 512KB) を超えている必要があります。

Amazon RDS インスタンスで使用可能な vCPU の数とテーブルのインデックスの数に基づいて `max_parallel_maintenance_workers` 設定を調整し、バキューム処理のターンアラウンド時間を最適化できます。

詳細については、「[Parallel vacuuming in Amazon RDS for PostgreSQL and Amazon Aurora PostgreSQL](https://aws.amazon.com/blogs/database/parallel-vacuuming-in-amazon-rds-for-postgresql-and-amazon-aurora-postgresql/)」を参照してください。

## バキューム処理対象のテーブルまたはデータベースが多すぎる
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables"></a>

PostgreSQL の「[The Autovacuum Daemon](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM')」ドキュメントで説明されているように、自動バキュームデーモンは複数のプロセスで動作します。このプロセスには、システム内の各データベースの自動バキュームワーカープロセスを開始する、永続的な自動バキュームランチャーが含まれます。ランチャーは、データベースあたり約 `autovacuum_naptime` 秒ごとにこれらのワーカーを開始するようにスケジュールします。

N 個のデータベースでは、新しいワーカーはおおよそ [`autovacuum_naptime`/N 秒] ごとに開始されます。ただし、同時ワーカーの合計数は `autovacuum_max_workers` 設定によって制限されます。バキューム処理を必要とするデータベースまたはテーブルの数がこの制限を超えると、ワーカーが利用可能になり次第すぐに次のデータベースまたはテーブルが処理されます。

多数の大きなテーブルやデータベースで同時にバキューム処理が必要な場合、使用可能なすべての自動バキュームワーカーが長時間占有され、他のテーブルやデータベースのメンテナンスに遅延が生じる可能性があります。トランザクションレートが高い環境では、このボトルネックがすぐに増大し、Amazon RDS インスタンス内で循環バキュームの問題が発生する可能性があります。

`postgres_get_av_diag()` が多数のテーブルまたはデータベースを検出すると、次の推奨事項が提示されます。

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.
```

**ガイダンス**

**autovacuum\$1max\$1workers を増やす**

バキューム処理を迅速化するために、`autovacuum_max_workers` パラメータを調整して同時実行の自動バキュームワーカーを増やすことをお勧めします。パフォーマンスのボトルネックが続く場合は、Amazon RDS インスタンスをより多くの vCPU を持つクラスにスケールアップすることを検討してください。これにより、並列処理機能をさらに向上させることができます。

## (循環を防ぐための) 積極的なバキューム処理が実行されている
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum"></a>

PostgreSQL のデータベースの経過時間 (MaximumUsedTransactionIDs) は、(循環を防ぐための) 積極的なバキューム処理が正常に完了した場合にのみ減少します。このバキューム処理が終了するまで、トランザクションレートに応じて経過時間は増加し続けます。

`postgres_get_av_diag()` 関数が積極的なバキュームを検出すると、次の `NOTICE` を生成します。ただし、この出力は、バキュームが少なくとも 2 分間アクティブになった後にのみトリガーされます。

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```

積極的なバキュームの詳細については、「[When an aggressive vacuum is already running](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)」を参照してください。

次のクエリを使用して、積極的なバキュームが進行中かどうかを確認できます。

```
SELECT
    a.xact_start AS start_time,
    v.datname "database",
    a.query,
    a.wait_event,
    v.pid,
    v.phase,
    v.relid::regclass,
    pg_size_pretty(pg_relation_size(v.relid)) AS heap_size,
    (
        SELECT
            string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ')
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS index_sizes,
    trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct,
    v.index_vacuum_count || '/' || (
        SELECT
            count(*)
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS step2_vacuum_indexes,
    trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct,
    age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar
FROM
    pg_stat_activity a
    INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;
```

出力の query 列をチェックすることで、(循環を防ぐための) 積極的なバキュームであるかどうかを判断できます。「to prevent wraparound」という語句は、それが積極的なバキュームであることを示しています。

```
query                  | autovacuum: VACUUM public.t3 (to prevent wraparound)
```

例えば、トランザクション経過時間が 10 億の時点でブロック要因があり、同じトランザクション経過時間での循環を防ぐために積極的なバキューム処理を必要とするテーブルがあるとします。さらに、トランザクション経過時間が 7 億 5,000 万の時点で別のブロック要因もあります。トランザクション経過時間 10 億でのブロック要因をクリアしても、トランザクション経過時間はすぐに 7 億 5,000 万には低下しません。積極的なバキューム処理を必要とするテーブル、または経過時間が 7 億 5,000 万を超えるトランザクションが完了するまで、高いままとなります。この間、PostgreSQL クラスターのトランザクション経過時間は増加し続けます。バキューム処理が完了すると、トランザクションの経過時間は 7 億 5,000 万に低下しますが、さらにバキューム処理が完了するまで再び増加し始めます。このサイクルは、最終的にトランザクション経過時間が `autovacuum_freeze_max_age` で指定された Amazon RDS インスタンスの設定レベルに低下するまで、これらの条件が存続する限り続きます。

# RDS for PostgreSQL の NOTICE メッセージの説明
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE"></a>

 `postgres_get_av_diag()` 関数は、次の NOTICE メッセージを提供します。

**経過時間がまだモニタリングしきい値に達していない場合**  
ブロック要因を識別するための `postgres_get_av_diag()` のモニタリングしきい値は、デフォルトで 5 億トランザクションです。`postgres_get_av_diag()` で次の NOTICE が生成された場合は、トランザクション経過時間がまだこのしきい値に達していないことを示します。  

```
NOTICE: postgres_get_av_diag() checks for blockers that prevent aggressive vacuums only, it does so only after exceeding dvb_threshold which is 500,000,000 and age of this PostgreSQL cluster is currently at 2.
```

**トランザクション ID の経過時間が最も古いデータベースに接続していない**  
`postgres_get_av_diag()` 関数は、トランザクション ID の経過時間が最も古いデータベースに接続したときに、最も正確な出力を提供します。`postgres_get_av_diag()` によって報告されたトランザクション ID の経過時間が最も古いデータベースが、「my\$1database」とは異なる場合があります。正しいデータベースに接続していない場合、次の NOTICE が生成されます。  

```
NOTICE: You are not connected to the database with the age of oldest transaction ID. Connect to my_database database and run postgres_get_av_diag() for accurate reporting.
```
トランザクション経過時間が最も古いデータベースに接続することは、次の理由で重要です。  
+ **一時テーブルのブロック要因の識別:** 一時テーブルのメタデータは各データベースに固有のため、通常、一時テーブルは作成されたデータベースにあります。ただし、一時テーブルが上位のブロック要因となり、最も古いトランザクションを持つデータベースに存在する状況では、誤解が生じる可能性があります。適切なデータベースに接続することで、一時テーブルのブロック要因を正確に識別できます。
+ **遅いバキュームの診断:** インデックスメタデータとテーブル数の情報はデータベース固有であり、バキュームが遅い問題の診断に必要です。

**トランザクションの経過時間が最も古いデータベースが、rdsadmin または template0 データベースにある**  
場合によっては、`rdsadmin` または `template0` データベースが、トランザクション ID の経過時間が最も古いデータベースとして識別される場合があります。このような場合、`postgres_get_av_diag()` で次の NOTICE が発行されます。  

```
NOTICE: The database with the age of oldest transaction ID is rdsadmin or template0, reach out to support if the reported blocker is in rdsadmin or template0.
```
リストされたブロック要因がこれら 2 つのデータベースのいずれからも発生していないことを確認します。ブロック要因が `rdsadmin` または `template0` のいずれかに存在すると報告された場合は、サポートに問い合わせてください。ユーザーはこれらのデータベースにはアクセスできず、サポートが必要です。  
`rdsadmin` と `template0` データベースのいずれかに上位のブロック要因が含まれている可能性はほとんどありません。

**積極的なバキュームがすでに実行されている場合**  
`postgres_get_av_diag()` 関数は、積極的なバキューム処理が実行されているときに報告を行うように設計されていますが、この出力はバキュームが少なくとも 1 分間アクティブになった後にのみトリガーされます。この意図的な遅延によって、誤検出の可能性が低くなります。待機することで、有効で重要なバキュームのみが報告され、バキュームアクティビティのより正確で信頼性の高いモニタリングが可能になります。  
`postgres_get_av_diag()` 関数は、進行中の 1 つ以上の積極的なバキュームを検出すると、次の NOTICE を生成します。  

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```
NOTICE に示されているように、バキュームのパフォーマンスを引き続きモニタリングします。積極的なバキュームの詳細については、「[(循環を防ぐための) 積極的なバキューム処理が実行されている](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)」を参照してください。

**自動バキュームがオフの場合**  
データベースインスタンスで自動バキュームが無効になっている場合、`postgres_get_av_diag()` 関数は次の NOTICE を生成します。  

```
NOTICE: Autovacuum is OFF, we strongly recommend to enable it, no restart is necessary.
```
自動バキュームは、RDS for PostgreSQL DB インスタンスの重要な機能であり、スムーズなデータベース操作を実現します。古い行バージョンを自動的に削除し、ストレージ領域を再利用して、テーブルの肥大化を防止することで、テーブルとインデックスの効率が維持され、パフォーマンスが最適化されます。さらに、Amazon RDS インスタンスのトランザクションを停止する可能性のある、トランザクション ID の循環も防止します。自動バキュームを無効にすると、データベースのパフォーマンスと安定性が長期的に低下する可能性があるため、常に有効にしておくことをお勧めします。詳細については、「[Understanding autovacuum in RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)」を参照してください。  
自動バキュームをオフにしても、積極的なバキュームは停止しません。積極的なバキュームは、テーブルが `autovacuum_freeze_max_age` しきい値に達すると実行されます。

**残っているトランザクションの数が非常に少ない**  
`postgres_get_av_diag()` 関数は、循環バキュームが差し迫った場合に次の NOTICE を生成します。この NOTICE は、Amazon RDS インスタンスが新しいトランザクションを拒否するまであと 1 億トランザクションに差し迫った場合に発行されます。  

```
WARNING: Number of transactions remaining is critically low, resolve issues with autovacuum or perform manual VACUUM FREEZE before your instance stops accepting transactions.
```
データベースのダウンタイムを回避するために、直ちにアクションが必要です。バキューム操作を注意深くモニタリングし、トランザクションの失敗を防ぐために、影響を受けるデータベースで `VACUUM FREEZE` を手動で開始することを検討する必要があります。