

# Amazon RDS for PostgreSQL で PostgreSQL 拡張機能を使用する
<a name="Appendix.PostgreSQL.CommonDBATasks.Extensions"></a>

PostgreSQL は、さまざまな拡張機能やモジュールをインストールすることで、機能を拡張することができます。例えば、空間データを操作するには、PostGIS 拡張機能をインストールして使用します。詳細については、「[PostGIS 拡張機能を使用した空間データの管理](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md)」を参照してください。別の例として、非常に大きなテーブルへのデータ入力を改善する場合は、`pg_partman` 拡張機能を使用したデータのパーティション化を検討できます。詳細については[pg\$1partman エクステンションによる PostgreSQL パーティションの管理](PostgreSQL_Partitions.md)を参照してください。

**注記**  
RDS for PostgreSQL は、DB インスタンスに追加できる `pg_tle` 拡張機能を通じて、Trusted Language Extensions for PostgreSQL をサポートしています。この拡張を使用することで、開発者は安全な環境で独自の PostgreSQL 拡張を作成できるため、セットアップと設定の要件が簡素化されます。`pg_tle` 拡張機能をサポートする RDS for PostgreSQL のバージョンと詳細については、「[Trusted Language Extensions for PostgreSQL を使用した操作](PostgreSQL_trusted_language_extension.md)」を参照してください。

場合によっては、拡張機能をインストールする代わりに、Aurora PostgreSQL DB クラスターのカスタム DB クラスターパラメータグループの `shared_preload_libraries` リストに特定のモジュールを追加することもできます。通常、デフォルトの DB クラスターパラメータグループでは、`pg_stat_statements` のみが読み込まれますが、リストに追加できるモジュールは他にもいくつかあります。例えば、[PostgreSQL pg\$1cron エクステンションによるメンテナンスのスケジューリング](PostgreSQL_pg_cron.md) で説明されているように、`pg_cron` モジュールを追加することでスケジュール機能を追加できます。別の例として、`auto_explain` モジュールをロードすることでクエリ実行計画を記録できます。詳細については、AWS ナレッジセンターの「[クエリ実行計画のログ記録](https://aws.amazon.com/premiumsupport/knowledge-center/rds-postgresql-tune-query-performance/#)」をご覧ください。

RDS for PostgreSQL のバージョンによっては、拡張機能をインストールする際に、以下のような `rds_superuser` の権限が必要になる場合があります。
+ RDS for PostgreSQL バージョン 12 以前のバージョンでは、拡張機能をインストールする際に `rds_superuser` の権限が必要となります。
+ RDS for PostgreSQL バージョン 13 以降のバージョンでは、特定のデータベースインスタンスに対する作成権限を持つユーザー (ロール) は、*信頼できる拡張機能*をインストールして使用することができます。信頼できる拡張機能のリストについては、「[PostgreSQL 信頼できるエクステンション](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.Extensions.Trusted)」を参照してください。

また、RDS for PostgreSQL DBインスタンスにインストール可能な拡張機能は、`rds.allowed_extensions` パラメータにリストアップして、正確に指定することができます。詳細については、「[PostgreSQL エクステンションのインストールを制限する](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)」を参照してください。

`rds_superuser` ロールの詳細については、「[PostgreSQL のロールとアクセス権限について](Appendix.PostgreSQL.CommonDBATasks.Roles.md)」を参照してください。

**Topics**
+ [orafce 拡張機能の関数の使用](Appendix.PostgreSQL.CommonDBATasks.orafce.md)
+ [PostgreSQL での Amazon RDS 委任拡張機能サポートの使用](RDS_delegated_ext.md)
+ [pg\$1partman エクステンションによる PostgreSQL パーティションの管理](PostgreSQL_Partitions.md)
+ [pgAudit を使用してデータベースのアクティビティを記録する](Appendix.PostgreSQL.CommonDBATasks.pgaudit.md)
+ [PostgreSQL pg\$1cron エクステンションによるメンテナンスのスケジューリング](PostgreSQL_pg_cron.md)
+ [pglogical を使用してインスタンス間でデータを同期する](Appendix.PostgreSQL.CommonDBATasks.pglogical.md)
+ [pgactive を使用したアクティブ/アクティブレプリケーションのサポート](Appendix.PostgreSQL.CommonDBATasks.pgactive.md)
+ [pg\$1repack 拡張機能を使用して、テーブルやインデックスの膨張を抑制する](Appendix.PostgreSQL.CommonDBATasks.pg_repack.md)
+ [PLV8 拡張機能のアップグレードおよび使用](PostgreSQL.Concepts.General.UpgradingPLv8.md)
+ [PL/Rust を使って Rust 言語で PostgreSQL 関数を記述する](PostgreSQL.Concepts.General.Using.PL_Rust.md)
+ [PostGIS 拡張機能を使用した空間データの管理](Appendix.PostgreSQL.CommonDBATasks.PostGIS.md)

# orafce 拡張機能の関数の使用
<a name="Appendix.PostgreSQL.CommonDBATasks.orafce"></a>

orafce 拡張機能は、Oracle データベースから関数とパッケージのサブセットをエミュレートする関数と演算子を提供します。Oracle 拡張機能を使用すると、Oracle アプリケーションを PostgreSQL に簡単に移植できます。この拡張機能は、RDS for PostgreSQL バージョン 9.6.6 以降でサポートされています。orafce についての詳細は、GitHub で「[orafce](https://github.com/orafce/orafce)」を参照してください。

**注記**  
RDS for PostgreSQL では、orafce 拡張機能の一部である `utl_file` パッケージがサポートされていません。これは、`utl_file` スキーマ関数が、基になるモストへのスーパーユーザーアクセスに必要なオペレーティングシステムテキストファイルで読み書き操作を実行するためです。マネージド型サービスの RDS for PostgreSQL では、ホストアクセスが許可されません。

**orafce エクステンションを使用するには**

1. DB インスタンスの作成で使用したプライマリユーザー名を使用して DB インスタンスに接続します。

   同じ DB インスタンスにある別のデータベースで orafce をオンにする場合は、`/c dbname` psql コマンドを使用します。このコマンドを使用すると、接続を開始した後にプライマリデータベースから変更できます。

1. `CREATE EXTENSION` ステートメントを使用して、orafce 拡張機能をオンにします。

   ```
   CREATE EXTENSION orafce;
   ```

1. `ALTER SCHEMA` ステートメントを使用して、oracle スキーマの所有権を rds\$1superuser ロールに転送します。

   ```
   ALTER SCHEMA oracle OWNER TO rds_superuser;
   ```

   oracle スキーマの所有者のリストを表示する場合は、`\dn` psql コマンドを使用します。

# PostgreSQL での Amazon RDS 委任拡張機能サポートの使用
<a name="RDS_delegated_ext"></a>

PostgreSQL に対して Amazon RDS 委任拡張機能のサポートを使用すると、拡張機能管理を `rds_superuser` である必要のないユーザーに委任できます。この委任拡張機能のサポートにより、`rds_extension` という新しいロールが作成され、他の拡張機能を管理するには、これをユーザーに割り当てる必要があります。このロールは、拡張機能を作成、更新、削除できます。

RDS DB インスタンスにインストール可能な拡張機能は、`rds.allowed_extensions` パラメータにそれらをリストアップして指定することができます。詳細については、「[Amazon RDS for PostgreSQL で PostgreSQL 拡張機能を使用する](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Extensions.html)」を参照してください。

`rds.allowed_delegated_extensions` パラメータを使用して、`rds_extension` ロールでユーザーが管理できる拡張機能のリストを制限できます。

委任拡張機能のサポートは、次のバージョンで利用できます。
+ すべての上位バージョン
+ 16.4 以降の 16 バージョン
+ 15.8 以降の 15 バージョン
+ 14.13 以降の 14 バージョン
+ 13.16 以降の 13 バージョン
+ 12.20 以降の 12 バージョン

**Topics**
+ [ユーザーに対する委任拡張機能のサポートの有効化](#RDSPostgreSQL.delegated_ext_mgmt)
+ [PostgreSQL での RDS 委任拡張機能サポートで使用される設定](#RDSPostgreSQL.delegated_ext_config)
+ [委任拡張機能のサポートの無効化](#RDSPostgreSQL.delegated_ext_disable)
+ [Amazon RDS 委任拡張機能サポートの使用のメリット](#RDSPostgreSQL.delegated_ext_benefits)
+ [PostgreSQL での Amazon RDS 委任拡張機能サポートの制限](#RDSPostgreSQL.delegated_ext_limit)
+ [特定の拡張機能に必要なアクセス許可](#RDSPostgreSQL.delegated_ext_perm)
+ [セキュリティに関する考慮事項](#RDSPostgreSQL.delegated_ext_sec)
+ [DROP EXTENSION CASCADE を無効化](#RDSPostgreSQL.delegated_ext_drop)
+ [委任拡張機能サポートを使用して追加できる拡張機能の例](#RDSPostgreSQL.delegated_ext_support)

## ユーザーに対する委任拡張機能のサポートの有効化
<a name="RDSPostgreSQL.delegated_ext_mgmt"></a>

ユーザーに対して委任拡張機能のサポートを有効にするには、以下を実行する必要があります。

1. **ユーザーに `rds_extension` ロールを付与する** – `rds_superuser` としてデータベースに接続し、次のコマンドを実行します。

   ```
   Postgres => grant rds_extension to user_name;
   ```

1. **委任されたユーザーが管理できる拡張機能のリストを設定する** – `rds.allowed_delegated_extensions` では、DB クラスターパラメータで `rds.allowed_extensions` を使用して、使用可能な拡張機能のサブセットを指定できます。これは、次のいずれかのレベルで実行できます。
   + クラスターまたはインスタンスパラメータグループで、AWS マネジメントコンソール または API を使用します。詳細については、「[Amazon RDS のパラメータグループ](USER_WorkingWithParamGroups.md)」を参照してください。
   + データベースレベルで次のコマンドを使用します。

     ```
     alter database database_name set rds.allowed_delegated_extensions = 'extension_name_1,
                         extension_name_2,...extension_name_n';
     ```
   + ユーザーレベルで次のコマンドを使用します。

     ```
     alter user user_name set rds.allowed_delegated_extensions = 'extension_name_1,
                         extension_name_2,...extension_name_n';
     ```
**注記**  
`rds.allowed_delegated_extensions` 動的パラメータを変更した後にデータベースを再起動する必要はありません。

1. **拡張機能の作成プロセス中に作成されたオブジェクトへのアクセスを委任されたユーザーに許可する** – 特定の拡張機能では、`rds_extension` ロールを持つユーザーがオブジェクトにアクセスする前に、追加のアクセス許可を付与する必要があるオブジェクトが作成されます。`rds_superuser` は、それらのオブジェクトへのアクセス権を委任されたユーザーに付与する必要があります。オプションの 1 つは、イベントトリガーを使用して、委任されたユーザーにアクセス許可を自動的に付与することです。

   **イベントトリガーの例**

   `rds_extension` を持つ委任ユーザーに、拡張機能の作成によって作成されたオブジェクトに対するアクセス許可の設定を必要とする拡張機能の使用を許可する場合は、次のイベントトリガーの例をカスタマイズし、委任されたユーザーに完全な機能へのアクセスを許可する拡張機能のみを追加できます。このイベントトリガーは template1 (デフォルトのテンプレート) で作成できるため、template1 から作成されたすべてのデータベースにそのイベントトリガーがあります。委任されたユーザーが拡張機能をインストールすると、このトリガーは拡張機能によって作成されたオブジェクトの所有権を自動的に付与します。

   ```
   CREATE OR REPLACE FUNCTION create_ext()
   
     RETURNS event_trigger AS $$
   
   DECLARE
   
     schemaname TEXT;
     databaseowner TEXT;
   
     r RECORD;
   
   BEGIN
   
     IF tg_tag = 'CREATE EXTENSION' and current_user != 'rds_superuser' THEN
       RAISE NOTICE 'SECURITY INVOKER';
       RAISE NOTICE 'user: %', current_user;
       FOR r IN SELECT * FROM pg_catalog.pg_event_trigger_ddl_commands()
       LOOP
           CONTINUE WHEN r.command_tag != 'CREATE EXTENSION' OR r.object_type != 'extension';
   
           schemaname = (
               SELECT n.nspname
               FROM pg_catalog.pg_extension AS e
               INNER JOIN pg_catalog.pg_namespace AS n
               ON e.extnamespace = n.oid
               WHERE e.oid = r.objid
           );
   
           databaseowner = (
               SELECT pg_catalog.pg_get_userbyid(d.datdba)
               FROM pg_catalog.pg_database d
               WHERE d.datname = current_database()
           );
           RAISE NOTICE 'Record for event trigger %, objid: %,tag: %, current_user: %, schema: %, database_owenr: %', r.object_identity, r.objid, tg_tag, current_user, schemaname, databaseowner;
           IF r.object_identity = 'address_standardizer_data_us' THEN
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_gaz TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_lex TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.us_rules TO %I WITH GRANT OPTION;', schemaname, databaseowner);
           ELSIF r.object_identity = 'dict_int' THEN
               EXECUTE pg_catalog.format('ALTER TEXT SEARCH DICTIONARY %I.intdict OWNER TO %I;', schemaname, databaseowner);
           ELSIF r.object_identity = 'pg_partman' THEN
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.part_config_sub TO %I WITH GRANT OPTION;', schemaname, databaseowner);
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE %I.custom_time_partitions TO %I WITH GRANT OPTION;', schemaname, databaseowner);
           ELSIF r.object_identity = 'postgis_topology' THEN
               EXECUTE pg_catalog.format('GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
               EXECUTE pg_catalog.format('GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
               EXECUTE pg_catalog.format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
               EXECUTE pg_catalog.format('GRANT USAGE ON SCHEMA topology TO %I WITH GRANT OPTION;', databaseowner);
           END IF;
       END LOOP;
     END IF;
   END;
   $$ LANGUAGE plpgsql SECURITY DEFINER;
   
   CREATE EVENT TRIGGER log_create_ext ON ddl_command_end EXECUTE PROCEDURE create_ext();
   ```

## PostgreSQL での RDS 委任拡張機能サポートで使用される設定
<a name="RDSPostgreSQL.delegated_ext_config"></a>


| 設定名 | 説明 | デフォルト値 | 注意事項 | アクセス許可を変更または付与できるユーザー | 
| --- | --- | --- | --- | --- | 
| `rds.allowed_delegated_extensions` | このパラメータは、rds\$1extension ロールがデータベースで管理できる拡張機能を制限します。rds.allowed\$1extensions のサブセットである必要があります。 | 空の文字列 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/RDS_delegated_ext.html) このパラメータの設定の詳細については、「[ユーザーに対する委任拡張機能のサポートの有効化](#RDSPostgreSQL.delegated_ext_mgmt)」を参照してください。 | rds\$1superuser | 
| `rds.allowed_extensions` | このパラメータにより、カスタマーは RDS DB インスタンスにインストールできる拡張機能を制限できます。詳細については、「[PostgreSQL 拡張機能のインストールの制限](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)」を参照してください。 | "\$1" | デフォルトでは、このパラメータは「\$1」に設定されています。つまり、RDS for PostgreSQL および Aurora PostgreSQL でサポートされているすべての拡張機能は、必要な権限を持つユーザーが作成できます。 空の場合、RDS DB インスタンスに拡張機能をインストールできないことを意味します。 | 管理者 | 
| `rds-delegated_extension_allow_drop_cascade` | このパラメータは、`rds_extension` を持つユーザーがカスケードオプションを使用して拡張機能を削除する機能を制御します。 | 化 | デフォルトで、`rds-delegated_extension_allow_drop_cascade` は `off` に設定されています。つまり、`rds_extension` を持つユーザーは、カスケードオプションを使用して拡張機能を削除することはできません。 その機能を許可するには、`rds.delegated_extension_allow_drop_cascade` パラメータを `on` に設定する必要があります。 | rds\$1superuser | 

## 委任拡張機能のサポートの無効化
<a name="RDSPostgreSQL.delegated_ext_disable"></a>

**部分的にオフにする**  
委任されたユーザーは、新しい拡張機能を作成することはできませんが、既存の拡張機能を更新することはできます。
+ DB クラスターパラメータグループでデフォルト値に `rds.allowed_delegated_extensions` をリセットします。
+ データベースレベルで次のコマンドを使用します。

  ```
  alter database database_name reset rds.allowed_delegated_extensions;
  ```
+ ユーザーレベルで次のコマンドを使用します。

  ```
  alter user user_name reset rds.allowed_delegated_extensions;
  ```

**すべてオフにする**  
ユーザーから `rds_extension` ロールを取り消すと、ユーザーは標準のアクセス許可に戻ります。ユーザーは拡張機能を作成、更新、削除できなくなります。

```
postgres => revoke rds_extension from user_name;
```

## Amazon RDS 委任拡張機能サポートの使用のメリット
<a name="RDSPostgreSQL.delegated_ext_benefits"></a>

PostgreSQL に対して Amazon RDS 委任拡張機能のサポートを使用すると、拡張機能管理を `rds_superuser` ロールを持たないユーザーに対してセキュアに委任できます。この機能には次の利点があります。
+ 選択したユーザーに拡張機能管理を簡単に委任できます。
+ これには `rds_superuser` ロールは不要です。
+ 同じ DB クラスター内の異なるデータベースに対して、異なる拡張機能セットをサポートする機能を提供します。

## PostgreSQL での Amazon RDS 委任拡張機能サポートの制限
<a name="RDSPostgreSQL.delegated_ext_limit"></a>
+ 拡張機能の作成プロセス中に作成されたオブジェクトは、拡張機能が正しく機能するために追加の権限が必要になる場合があります。
+ 一部の拡張機能は、デフォルトで `log_fdw`、`pg_cron`、`pg_tle`、`pgactive`、`pglogical`、`postgis_raster`、`postgis_tiger_geocoder`、`postgis_topology` などの委任された拡張機能ユーザーが管理することはできません。

## 特定の拡張機能に必要なアクセス許可
<a name="RDSPostgreSQL.delegated_ext_perm"></a>

次の拡張機能を作成、使用、または更新するには、委任されたユーザーに次の関数、テーブル、スキーマに対する必要な権限が必要です。


| 所有権またはアクセス許可が必要な拡張機能 | 関数 | テーブル | スキーマ | テキスト検索ディクショナリ | Comment | 
| --- | --- | --- | --- | --- | --- | 
| address\$1standardizer\$1data\$1us | なし | us\$1gaz、us\$1lex、us\$1lex、I.us\$1rules | なし | なし | なし | 
| amcheck | bt\$1index\$1check、bt\$1index\$1parent\$1check | なし | なし | なし | なし | 
| dict\$1int | なし | なし | なし | intdict | なし | 
| pg\$1partman | なし | custom\$1time\$1partitions、part\$1config、part\$1config\$1sub | なし | なし | なし | 
| pg\$1stat\$1statements | なし | なし | なし | なし | なし | 
| PostGIS | st\$1tileenvelope | spatial\$1ref\$1sys | なし | なし | なし | 
| postgis\$1raster | なし | なし | なし | なし | なし | 
| postgis\$1topology | なし | トポロジ、レイヤー | トポロジ | なし | 委任されたユーザーはデータベース所有者であること | 
| log\$1fdw | create\$1foreign\$1table\$1for\$1log\$1file | なし | なし | なし | なし | 
| rds\$1tools | role\$1password\$1encryption\$1type | なし | なし | なし | なし | 
| postgis\$1tiger\$1geocoder | なし | geocode\$1settings\$1default, geocode\$1settings | tiger | なし | なし | 
| pg\$1freespacemap | pg\$1freespace | なし | なし | なし | なし | 
| pg\$1visibility | pg\$1visibility | なし | なし | なし | なし | 

## セキュリティに関する考慮事項
<a name="RDSPostgreSQL.delegated_ext_sec"></a>

 `rds_extension` ロールを持つユーザーは、接続権限を持つすべてのデータベースの拡張機能を管理できることに注意してください。委任されたユーザーが 1 つのデータベースの拡張機能を管理する場合は、各データベースのパブリックからすべての権限を取り消し、その特定のデータベースの接続権限を委任されたユーザーに明示的に付与することをお勧めします。

 ユーザーが複数のデータベースから情報にアクセスできる拡張機能がいくつかあります。これらの拡張機能を `rds.allowed_delegated_extensions` に追加する前に、`rds_extension` を付与するユーザーにクロスデータベース機能があることを確認してください。例えば、`postgres_fdw` と `dblink` は、同じインスタンスまたはリモートインスタンス上のデータベース間でクエリを実行する機能を提供します。`log_fdw` は postgres エンジンのログファイルを読み取ります。これらは、インスタンス内のすべてのデータベース用であり、複数のデータベースからのスロークエリやエラーメッセージが含まれている可能性があります。`pg_cron` は、DB インスタンスでスケジュールされたバックグラウンドジョブの実行を有効にし、別のデータベースで実行するようにジョブを設定できます。

## DROP EXTENSION CASCADE を無効化
<a name="RDSPostgreSQL.delegated_ext_drop"></a>

 `rds_extension` ロールを持つユーザーがカスケードオプションを使用して拡張機能を削除する機能は、`rds.delegated_extension_allow_drop_cascade` パラメータによって制御されます。デフォルトで、`rds-delegated_extension_allow_drop_cascade` は `off` に設定されています。つまり、`rds_extension` ロールを持つユーザーは、以下のクエリに示すように、カスケードオプションを使用して拡張機能を削除することはできません。

```
DROP EXTENSION CASCADE;
```

これにより、拡張機能に依存するオブジェクト、およびそれらのオブジェクトに依存するすべてのオブジェクトが自動的に削除されます。カスケードオプションを使用しようとすると、エラーが発生します。

 その機能を許可するには、`rds.delegated_extension_allow_drop_cascade` パラメータを `on` に設定する必要があります。

 `rds.delegated_extension_allow_drop_cascade` 動的パラメータを変更しても、データベースを再起動する必要はありません。これは、次のいずれかのレベルで実行できます。
+ クラスターまたはインスタンスパラメータグループで、AWS マネジメントコンソール または API を使用します。
+ データベースレベルで次のコマンドを使用する。

  ```
  alter database database_name set rds.delegated_extension_allow_drop_cascade = 'on';
  ```
+ ユーザーレベルで次のコマンドを使用する。

  ```
  alter role tenant_user set rds.delegated_extension_allow_drop_cascade = 'on';
  ```

## 委任拡張機能サポートを使用して追加できる拡張機能の例
<a name="RDSPostgreSQL.delegated_ext_support"></a>
+ `rds_tools`

  ```
  extension_test_db=> create extension rds_tools;
  CREATE EXTENSION
  extension_test_db=> SELECT * from rds_tools.role_password_encryption_type() where rolname = 'pg_read_server_files';
  ERROR: permission denied for function role_password_encryption_type
  ```
+ `amcheck`

  ```
  extension_test_db=> CREATE TABLE amcheck_test (id int);
  CREATE TABLE
  extension_test_db=> INSERT INTO amcheck_test VALUES (generate_series(1,100000));
  INSERT 0 100000
  extension_test_db=> CREATE INDEX amcheck_test_btree_idx ON amcheck_test USING btree (id);
  CREATE INDEX
  extension_test_db=> create extension amcheck;
  CREATE EXTENSION
  extension_test_db=> SELECT bt_index_check('amcheck_test_btree_idx'::regclass);
  ERROR: permission denied for function bt_index_check
  extension_test_db=> SELECT bt_index_parent_check('amcheck_test_btree_idx'::regclass);
  ERROR: permission denied for function bt_index_parent_check
  ```
+ `pg_freespacemap`

  ```
  extension_test_db=> create extension pg_freespacemap;
  CREATE EXTENSION
  extension_test_db=> SELECT * FROM pg_freespace('pg_authid');
  ERROR: permission denied for function pg_freespace
  extension_test_db=> SELECT * FROM pg_freespace('pg_authid',0);
  ERROR: permission denied for function pg_freespace
  ```
+ `pg_visibility`

  ```
  extension_test_db=> create extension pg_visibility;
  CREATE EXTENSION
  extension_test_db=> select * from pg_visibility('pg_database'::regclass);
  ERROR: permission denied for function pg_visibility
  ```
+ `postgres_fdw`

  ```
  extension_test_db=> create extension postgres_fdw;
  CREATE EXTENSION
  extension_test_db=> create server myserver foreign data wrapper postgres_fdw options (host 'foo', dbname 'foodb', port '5432');
  ERROR: permission denied for foreign-data wrapper postgres_fdw
  ```

# pg\$1partman エクステンションによる PostgreSQL パーティションの管理
<a name="PostgreSQL_Partitions"></a>

PostgreSQL テーブルパーティションは、データ入力とレポートにおける高性能な処理のためのフレームワークを提供します。大量のデータを非常に速く入力する必要があるデータベースには、パーティションを使用します。またパーティションは、大きなテーブルでより高速のクエリを提供します。パーティションは、必要とする I/O リソースが少ないため、データベースインスタンスに影響を与えずにデータを維持するのに役立ちます。

パーティションを使用すると、データをカスタムサイズのチャンクに分割して処理することができます。例えば、時間単位、日単位、週単位、月単位、四半期単位、年単位、カスタム、またはこれらの組み合わせなどの範囲のパーティションの時系列データを選択できます。時系列データの例では、テーブルを時間単位でパーティション化した場合、各パーティションには 1 時間のデータが含まれます。時系列テーブルを日単位でパーティション化した場合、パーティションには 1 日分のデータが保持されます。パーティションキーは、パーティションのサイズを制御します。

パーティション化されたテーブルで `INSERT` SQL コマンドまたは `UPDATE` SQL コマンドを使用すると、データベースエンジンはデータを適切なパーティションにルーティングします。データを格納する PostgreSQL テーブルパーティションは、メインテーブルの子テーブルです。

データベースクエリの読み取り中、PostgreSQL オプティマイザはクエリの `WHERE` 句を調べ、可能な場合、関連するパーティションだけにデータベーススキャンを行うよう指示します。

バージョン 10 以降、PostgreSQL は宣言的なパーティショニングを使用してテーブルパーティションを実装します。これは、ネイティブ PostgreSQL パーティションとも言います。PostgreSQL バージョン 10 より前は、トリガーを使用してパーティションを実装していました。

PostgreSQL テーブルパーティションは、次の機能を提供します。
+ 新しいパーティションの作成がいつでも可能。
+ 可変のパーティション範囲。
+ データ定義言語 (DDL) ステートメントを使用して、取り外し可能かつ再接続可能なパーティション。

  例えば、デタッチ可能なパーティションは、メインパーティションから履歴データを削除し、履歴データを分析用に保持する場合に便利です。
+ 新しいパーティションは、親のデータベーステーブルの以下のプロパティを継承します。
  + インデックス
  + プライマリキー (パーティションキー列を含める必要があります)
  + 外部キー
  + 検査制約
  + 参照
+ フルテーブルまたは各特定のパーティションのインデックスの作成。

個々のパーティションのスキーマを変更することはできません。ただし、パーティションに伝播される親テーブル (新しい列の追加など) は変更できます。

**Topics**
+ [PostgreSQL pg\$1partman エクステンションの概要](#PostgreSQL_Partitions.pg_partman)
+ [pg\$1partman エクステンションの有効化](#PostgreSQL_Partitions.enable)
+ [create\$1parent 関数を使用したパーティションの設定](#PostgreSQL_Partitions.create_parent)
+ [run\$1maintenance\$1proc 関数を使用したパーティションのメンテナンス設定](#PostgreSQL_Partitions.run_maintenance_proc)

## PostgreSQL pg\$1partman エクステンションの概要
<a name="PostgreSQL_Partitions.pg_partman"></a>

PostgreSQL `pg_partman` エクステンションを使用すると、テーブルパーティションの作成とメンテナンスを自動化できます。一般的な情報については、`pg_partman` ドキュメントの「[PG Partition Manager](https://github.com/pgpartman/pg_partman)」を参照してください。

**注記**  
`pg_partman` エクステンションは、RDS for PostgreSQL のバージョン 12.5 以降でサポートされています。

各パーティションを手動で作成する代わりに、次の設定で `pg_partman` を設定します。
+ パーティション化するテーブル
+ パーティションタイプ
+ パーティションキー
+ パーティションの粒度
+ パーティションの事前作成および管理オプション

PostgreSQL のパーティション化されたテーブルの作成後、`create_parent` 関数を呼び出して、そのテーブルを `pg_partman` に登録します。これにより、関数に渡すパラメータに基づいて、必要なパーティションを作成します。

`pg_partman` エクステンションには、設定したスケジュールに基づいて呼び出しを行うことでパーティションを自動的に管理できる `run_maintenance_proc` 関数も用意されています。必要に応じて適切なパーティションが作成されるようにするには、この関数を定期的に (時間単位など) 実行するようにスケジュールします。また、パーティションが自動的に削除されるようにすることもできます。

## pg\$1partman エクステンションの有効化
<a name="PostgreSQL_Partitions.enable"></a>

パーティションを管理する同じ PostgreSQL DB インスタンス内に複数のデータベースがある場合は、データベースごとに `pg_partman` エクステンションを有効にします。特定のデータベースで `pg_partman` エクステンションを有効にするには、パーティションメンテナンススキーマを作成した上で、次のように `pg_partman` エクステンションを作成します。

```
CREATE SCHEMA partman;
CREATE EXTENSION pg_partman WITH SCHEMA partman;
```

**注記**  
`pg_partman` エクステンションを作成するには、`rds_superuser` 権限が必要です。

次のようなエラーが表示された場合は、アカウントに `rds_superuser` 権限を付与するか、スーパーユーザーアカウントを使用します。

```
ERROR: permission denied to create extension "pg_partman"
HINT: Must be superuser to create this extension.
```

`rds_superuser` 権限を付与するには、スーパーユーザーアカウントを使用して接続し、以下のコマンドを実行します。

```
GRANT rds_superuser TO user-or-role;
```

pg\$1partman エクステンションの使用方法を示す例では、次のサンプルのデータベーステーブルとパーティションを使用します。このデータベースでは、タイムスタンプに基づいてパーティション化されたテーブルを使用します。スキーマ `data_mart` には、`events` という列を持つ `created_at` という名前のテーブルが含まれています。この `events` テーブルには、次の設定が含まれています。
+  プライマリキー `event_id` および `created_at`。パーティションのガイドに使用される列を含める必要があります。
+ `ck_valid_operation` テーブル列に値を適用するための検査制約 `operation`。
+ 2 つの外部キー。1 つ (`fk_orga_membership)`) は外部テーブル `organization` で、もう 1 つ (`fk_parent_event_id`) は自己参照外部キーです。
+ 2 つのインデックス。1 つ (`idx_org_id`) は外部キー用で、もう 1 つ (`idx_event_type`) はイベントタイプ用です。

次の DDL ステートメントは、各パーティションに自動的に含まれるこれらのオブジェクトを作成します。

```
CREATE SCHEMA data_mart;
CREATE TABLE data_mart.organization ( org_id BIGSERIAL,
        org_name TEXT,
        CONSTRAINT pk_organization PRIMARY KEY (org_id)  
    );

CREATE TABLE data_mart.events(
        event_id        BIGSERIAL, 
        operation       CHAR(1), 
        value           FLOAT(24), 
        parent_event_id BIGINT, 
        event_type      VARCHAR(25), 
        org_id          BIGSERIAL, 
        created_at      timestamp, 
        CONSTRAINT pk_data_mart_event PRIMARY KEY (event_id, created_at), 
        CONSTRAINT ck_valid_operation CHECK (operation = 'C' OR operation = 'D'), 
        CONSTRAINT fk_orga_membership 
            FOREIGN KEY(org_id) 
            REFERENCES data_mart.organization (org_id),
        CONSTRAINT fk_parent_event_id 
            FOREIGN KEY(parent_event_id, created_at) 
            REFERENCES data_mart.events (event_id,created_at)
    ) PARTITION BY RANGE (created_at);

CREATE INDEX idx_org_id     ON  data_mart.events(org_id);
CREATE INDEX idx_event_type ON  data_mart.events(event_type);
```



## create\$1parent 関数を使用したパーティションの設定
<a name="PostgreSQL_Partitions.create_parent"></a>

`pg_partman` エクステンションを有効にした後、`create_parent` 関数を使用して、パーティションメンテナンススキーマ内でパーティションの設定を行います。以下の例では、`events` で作成される [pg\$1partman エクステンションの有効化run\$1maintenance\$1proc 関数を使用したパーティションのメンテナンス設定](#PostgreSQL_Partitions.enable) テーブルの例を使用します。`create_parent` 関数を次のように呼び出します。

```
SELECT partman.create_parent( 
 p_parent_table => 'data_mart.events',
 p_control      => 'created_at',
 p_type         => 'range',
 p_interval     => '1 day',
 p_premake      => 30);
```

パラメータは次のとおりです。
+ `p_parent_table` - 親パーティションテーブル。このテーブルは既に存在しており、スキーマを含めて完全修飾である必要があります。
+ `p_control` - パーティションのベースとなる列。データタイプは、整数または時間ベースである必要があります。
+ `p_type` - タイプは `'range'` または `'list'` です。
+ `p_interval` - 各パーティションの時間間隔または整数の範囲。値の例は、`1 day`、`1 hour` などです。
+ `p_premake` - 新しい挿入をサポートするために事前に作成するパーティションの数。

`create_parent` 関数の詳細については、`pg_partman` ドキュメントの「[Creation Functions (関数の作成)](https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md#user-content-creation-functions)」を参照してください。

## run\$1maintenance\$1proc 関数を使用したパーティションのメンテナンス設定
<a name="PostgreSQL_Partitions.run_maintenance_proc"></a>

パーティションのメンテナンスオペレーションを実行して、自動的に新しいパーティションの作成、パーティションのデタッチ、または古いパーティションの削除ができます。パーティションのメンテナンスは、内部のスケジューラをスタートする `pg_partman` および `pg_cron` エクステンション の `run_maintenance_proc` 関数により異なります。`pg_cron` スケジューラは、データベースで定義された SQL ステートメント、関数、および手順を自動的に実行します。

次の例では、`events` で作成した [pg\$1partman エクステンションの有効化run\$1maintenance\$1proc 関数を使用したパーティションのメンテナンス設定](#PostgreSQL_Partitions.enable) テーブルの例を使用して、パーティションのメンテナンスオペレーションを自動的に実行するように設定します。前提条件にあるように、DB インスタンスのパラメータグループで、`shared_preload_libraries` パラメータに `pg_cron` を追加します。

```
CREATE EXTENSION pg_cron;

UPDATE partman.part_config 
SET infinite_time_partitions = true,
    retention = '3 months', 
    retention_keep_table=true 
WHERE parent_table = 'data_mart.events';
SELECT cron.schedule('@hourly', $$CALL partman.run_maintenance_proc()$$);
```

その後、前の例についてのステップバイステップの説明を確認できます。

1. DB インスタンスに関連付けられているパラメータグループを変更して、`pg_cron` を `shared_preload_libraries` パラメータ値に追加します。この変更を有効にするには、DB インスタンスの再起動が必要です。詳細については、「[Amazon RDS の DB パラメータグループのパラメータの変更](USER_WorkingWithParamGroups.Modifying.md)」を参照してください。

1. `CREATE EXTENSION pg_cron;` のアクセス許可を持つアカウントを使用して、コマンド `rds_superuser` を実行します。これにより、`pg_cron` エクステンションが有効になります。詳細については、「[PostgreSQL pg\$1cron エクステンションによるメンテナンスのスケジューリング](PostgreSQL_pg_cron.md)」を参照してください。

1. `UPDATE partman.part_config` コマンドを実行して、`data_mart.events` テーブルの `pg_partman` 設定を調整します。

1. `SET` . . .コマンドを実行して、以下の句を使用しながら、`data_mart.events` テーブルを設定します。

   1. `infinite_time_partitions = true,` - 制限なしで新しいパーティションを自動的に作成できるようにテーブルを設定します。

   1. `retention = '3 months',` - テーブルの最大保持期間を 3 か月に設定します。

   1. `retention_keep_table=true ` - 保存期間の期限が過ぎてもテーブルが自動的に削除されないように、テーブルを構成します。代わりに、保持期間より古いパーティションは、親テーブルからのみデタッチされます。

1. `SELECT cron.schedule` . . .コマンドを実行して、`pg_cron` 関数を呼び出します。この呼び出は、`pg_partman` メンテナンスプロシージャの `partman.run_maintenance_proc` が、スケジューラにより実行される頻度を定義します。この例では、プロシージャは 1 時間ごとに実行されます。

`run_maintenance_proc` 関数の詳細については、`pg_partman` ドキュメントの「[Maintenance Functions (メンテナンス機能)](https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md#maintenance-functions)」を参照してください。

# pgAudit を使用してデータベースのアクティビティを記録する
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit"></a>

金融機関、政府機関、および多くの業界では、*規制要件を満たすために監査ログ*を保存する必要があります。 RDS for PostgreSQL DB インスタンスで PostgreSQL 監査拡張機能 (pgAudit) を使用することで、監査人が通常必要とする詳細なレコードや規制要件を満たすための詳細なレコードをキャプチャできます。例えば、pgAudit 拡張機能を設定して、特定のデータベースやテーブルに加えられた変更を追跡したり、変更を加えたユーザーやその他の多くの詳細を記録したりできます。

pgAudit 拡張機能は、ログメッセージをより詳細に拡張することにより、ネイティブの PostgreSQL ログ記録インフラストラクチャの機能に基づいて構築されています。つまり、監査ログは、他のログメッセージを表示するのと同じ方法を使用します。PostgreSQL ログ記録の詳細については、「[ RDS for PostgreSQL データベースログファイル](USER_LogAccess.Concepts.PostgreSQL.md)」を参照してください。

pgAudit 拡張機能は、クリアテキストパスワードなどの機密データをログから編集します。 RDS for PostgreSQL DB インスタンスが、[ RDS for PostgreSQL DB インスタンスのクエリログ記録をオンにする](USER_LogAccess.Concepts.PostgreSQL.Query_Logging.md) で説明されているようにデータ操作言語 (DML) ステートメントをログに記録するように設定されている場合は、PostgreSQL Audit 拡張機能を使用することでクリアテキストパスワードの問題を回避できます。

データベースインスタンスの監査は、きわめて詳細に構成できます。すべてのデータベースとすべてのユーザーを監査できます。また、特定のデータベース、ユーザー、その他のオブジェクトのみを監査することもできます。特定のユーザーやデータベースを監査対象から明示的に除外することもできます。詳細については、「[監査ログからのユーザーまたはデータベースの除外](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md)」を参照してください。

キャプチャできる詳細の量を考慮すると、pgAudit を使用する場合はストレージ消費量を監視することをお勧めします。

pgAudit 拡張モジュールは、使用可能なすべての RDS for PostgreSQL バージョン。利用可能な RDS for PostgreSQL バージョンでサポートされている pgAudit バージョンのリストについては、*Amazon RDS for PostgreSQL リリースノート*の「[Amazon RDS for PostgreSQL の拡張バージョン](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)」を参照してください。

**Topics**
+ [pgAudit 拡張機能のセットアップ](Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.md)
+ [データベースオブジェクトの監査](Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing.md)
+ [監査ログからのユーザーまたはデータベースの除外](Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db.md)
+ [pgAudit 拡張機能のリファレンス](Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.md)

# pgAudit 拡張機能のセットアップ
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup"></a>

RDS for PostgreSQL DB インスタンス に pgAudit 拡張機能を設定するには、まず RDS for PostgreSQL DB インスタンスのカスタム DB パラメータグループの共有ライブラリに pgAudit を追加します。カスタム DB パラメータグループの作成については、「[Amazon RDS のパラメータグループ](USER_WorkingWithParamGroups.md)」を参照してください。次に、pgAudit 拡張機能をインストールします。最後に、監査するデータベースとオブジェクトを指定します。このセクションの手順で、方法を示します。AWS マネジメントコンソール または AWS CLI を使用できます。

これらすべてのタスクを実行するには、`rds_superuser` ロールとして権限が必要です。

以下の手順では、 RDS for PostgreSQL DB インスタンスがカスタム DB パラメータグループに関連付けられていることを前提としています。

## コンソール
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CON"></a>

**pgAudit 拡張機能をセットアップするには**

1. AWS マネジメントコンソール にサインインし、Amazon RDS コンソール [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/) を開きます。

1. ナビゲーションペインで、 RDS for PostgreSQL DB インスタンスを選択します。

1. の **[Configuration]** (設定) タブを開きます。RDS for PostgreSQL DB インスタンス。インスタンスの詳細の中から、**パラメータグループ**のリンクを見つけてください。

1. リンクを選択して、に関連するカスタムパラメータを開きます。RDS for PostgreSQL DB インスタンス。

1. **パラメータ**検索フィールドに、`shared_pre` を入力して `shared_preload_libraries` パラメータを検索します。

1. プロパティ値にアクセスするには、**[Edit parameters]** (パラメータの編集) を選択します。

1. **[Values]** (値) フィールドのリストに `pgaudit` を追加します。値のリスト内の項目を区切るにはカンマを使用します。  
![\[pgAudit が追加された shared_preload_libaries パラメータの画像。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pgaudit.png)

1.  RDS for PostgreSQL DB instance を再起動して、`shared_preload_libraries` パラメータの変更を有効にします。

1. インスタンスが使用可能になったら、pgAudit が初期化されていることを確認します。`psql` を使用して RDS for PostgreSQL DB インスタンスに接続し、次のコマンドを実行します。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

1. pgAudit を初期化すると、拡張機能を作成できるようになりました。`pgaudit` 拡張機能はデータ定義言語 (DDL) ステートメントを監査するためのイベントトリガーをインストールするため、ライブラリを初期化した後に拡張機能を作成する必要があります。

   ```
   CREATE EXTENSION pgaudit;
   ```

1. `psql` セッションを終了します。

   ```
   labdb=> \q
   ```

1. AWS マネジメントコンソール にサインインし、Amazon RDS コンソール [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/) を開きます。

1. リストで `pgaudit.log` パラメータを検索し、ユースケースに応じた値に設定します。例えば、次の画像に示すように `pgaudit.log` パラメータを `write` に設定すると、ログへの挿入、更新、削除、およびその他のタイプの変更がキャプチャされます。  
![\[設定を含む pgaudit.log パラメータの画像。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/images/rpg_set_pgaudit-log-level.png)

   `pgaudit.log` パラメータには、次のいずれかの値を選択することもできます。
   + none – これはデフォルトです。データベースの変更は記録されません。
   + すべて — すべてをログに記録します (読み取り、書き込み、関数、ロール、DDL、その他)。
   + ddl – `ROLE` クラスに含まれていない、すべてのデータ定義言語 (DDL) ステートメントのログ記録。
   + function – 関数呼び出し、および `DO` ブロックのログ記録。
   + misc – `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM`、`SET` など、さまざまなコマンドのログ記録。
   + read – `SELECT` および `COPY` のログ記録 (ソースがリレーション (テーブルなどの) またはクエリの場合)。
   + role – `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE`、`DROP ROLE` など、ロールと権限に関連するステートメントのログ記録。
   + write – `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE`、および `COPY` のログ記録 (送信先がリレーション (テーブル) の場合)。

1. [**Save changes**] (変更の保存) をクリックします。

1. Amazon RDS コンソール ([https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)) を開きます。

1. データベースリストから、 RDS for PostgreSQL DB インスタンスを選択します。

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.CLI"></a>

**pgAudit をセットアップするには**

AWS CLI を使用して pgAudit を設定するには、次の手順に示すように、[modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) オペレーションを呼び出してカスタムパラメータグループの監査ログパラメータを変更します。

1. 次の AWS CLI コマンドを使用して`shared_preload_libraries`パラメータに `pgaudit` を追加します。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=pgaudit,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 次の AWS CLI コマンドを使用して RDS for PostgreSQL DB インスタンスを再起動し、pgaudit ライブラリを初期化します。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. インスタンスが使用可能になると、`pgaudit` が初期化されていることを確認できます。`psql` を使用して RDS for PostgreSQL DB インスタンスに接続し、次のコマンドを実行します。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pgaudit
   (1 row)
   ```

   pgAudit を初期化すると、拡張機能を作成できるようになりました。

   ```
   CREATE EXTENSION pgaudit;
   ```

1. AWS CLI を使用できるように `psql` セッションを終了します。

   ```
   labdb=> \q
   ```

1. 次の AWS CLI コマンドを使用して、セッション監査ログによって記録するステートメントのクラスを指定します。この例では、`pgaudit.log` パラメータを `write` に設定し、ログへの挿入、更新、削除をキャプチャします。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=pgaudit.log,ParameterValue=write,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

   `pgaudit.log` パラメータには、次のいずれかの値を選択することもできます。
   + none – これはデフォルトです。データベースの変更は記録されません。
   + すべて — すべてをログに記録します (読み取り、書き込み、関数、ロール、DDL、その他)。
   + ddl – `ROLE` クラスに含まれていない、すべてのデータ定義言語 (DDL) ステートメントのログ記録。
   + function – 関数呼び出し、および `DO` ブロックのログ記録。
   + misc – `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM`、`SET` など、さまざまなコマンドのログ記録。
   + read – `SELECT` および `COPY` のログ記録 (ソースがリレーション (テーブルなどの) またはクエリの場合)。
   + role – `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE`、`DROP ROLE` など、ロールと権限に関連するステートメントのログ記録。
   + write – `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE`、および `COPY` のログ記録 (送信先がリレーション (テーブル) の場合)。

   次の AWS CLI コマンドを使用して、 RDS for PostgreSQL DB インスタンスを再起動します。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# データベースオブジェクトの監査
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.auditing"></a>

 RDS for PostgreSQL DB インスタンスに pgAudit をセットアップし、要件に合わせて設定すると、より詳細な情報が PostgreSQL ログに取得されます。例えば、デフォルトの PostgreSQL ログ設定はデータベーステーブルに変更が加えられた日付と時刻を識別しますが、pgAudit 拡張機能では、拡張機能のパラメータの設定方法に応じて、スキーマ、変更を行ったユーザー、その他の詳細をログエントリに含めることができます。監査を設定して、次の方法で変更を追跡できます。
+ セッションごとに、ユーザー別。セッションレベルでは、完全修飾コマンドテキストをキャプチャできます。
+ オブジェクトごとに、ユーザー別、データベース別。

オブジェクト監査機能は、システムで `rds_pgaudit` ロールを作成し、そのロールをカスタムパラメータグループの `pgaudit.role` パラメータに追加したときに有効になります。デフォルトでは、`pgaudit.role` パラメータは設定されておらず、許容される値は `rds_pgaudit` だけです。以下の手順は、`pgaudit` が初期化され、[pgAudit 拡張機能のセットアップ](Appendix.PostgreSQL.CommonDBATasks.pgaudit.basic-setup.md) の手順に従って `pgaudit` 拡張機能を作成したことを前提としています。

![\[pgAudit をセットアップした後の PostgreSQL ログファイルの画像。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/images/pgaudit-log-example.png)


この例に示すように、「LOG: AUDIT: SESSION」行には、テーブルとそのスキーマなどの詳細情報が表示されます。

**オブジェクト監査をセットアップするには**

1. `psql` を使用して RDS for PostgreSQL DB インスタンスに接続します。

   ```
   psql --host=your-instance-name.aws-region.rds.amazonaws.com --port=5432 --username=postgrespostgres --password --dbname=labdb
   ```

1. 次のコマンドを使用して、`rds_pgaudit` というデータベースロールを作成します。

   ```
   labdb=> CREATE ROLE rds_pgaudit;
   CREATE ROLE
   labdb=>
   ```

1. `psql` セッションを終了します。

   ```
   labdb=> \q
   ```

   次のステップでは、AWS CLI を使用してカスタムパラメータグループの監査ログパラメータを変更します。

1. 次の AWS CLI コマンドを使用して、`pgaudit.role` パラメータを `rds_pgaudit` に設定します。デフォルトでは、このパラメータは空で、`rds_pgaudit` は、唯一の許容値です。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=pgaudit.role,ParameterValue=rds_pgaudit,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 次の AWS CLI コマンドを使用して RDS for PostgreSQL DB インスタンスを再起動し、パラメータの変更を有効にします。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. 次のコマンドを実行して、`pgaudit.role` が `rds_pgaudit` に設定されたことを確認します。

   ```
   SHOW pgaudit.role;
   pgaudit.role 
   ------------------
   rds_pgaudit
   ```

pgAudit ログ記録をテストするには、監査するサンプルコマンドをいくつか実行します。例えば、次のコマンドを実行します。

```
CREATE TABLE t1 (id int);
GRANT SELECT ON t1 TO rds_pgaudit;
SELECT * FROM t1;
id 
----
(0 rows)
```

データベースログには、次のようなエントリが含まれます。

```
...
2017-06-12 19:09:49 UTC:...:rds_test@postgres:[11701]:LOG: AUDIT:
OBJECT,1,1,READ,SELECT,TABLE,public.t1,select * from t1;
...
```

ログの表示方法については、「[Amazon RDS ログファイルのモニタリング](USER_LogAccess.md)」を参照してください。

pgAudit 拡張機能の詳細については、GitHub で「[pgAudit](https://github.com/pgaudit/pgaudit/blob/master/README.md)」を参照してください。

# 監査ログからのユーザーまたはデータベースの除外
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.exclude-user-db"></a>

[ RDS for PostgreSQL データベースログファイル](USER_LogAccess.Concepts.PostgreSQL.md) で説明したように、PostgreSQL ログはストレージ容量を使用します。pgAudit 拡張機能を使用すると、追跡する変更に応じて、ログに収集されるデータの量が、程度の差はありますが、増加します。内のすべてのユーザーまたはデータベースを監査する必要はないかもしれません。RDS for PostgreSQL DB インスタンス。

ストレージへの影響を最小限に抑え、監査記録を不必要にキャプチャしないようにするには、ユーザーとデータベースを監査対象から除外できます。特定のセッション内のロギングを変更することもできます。次の例は、その方法を示しています。

**注記**  
セッションレベルのパラメータ設定は、 RDS for PostgreSQL DB インスタンスのカスタム DB パラメータグループの設定よりも優先されます。データベースユーザーに監査ログ設定の設定をバイパスさせたくない場合は、必ず権限を変更してください。

 RDS for PostgreSQL DB インスタンスが、すべてのユーザーとデータベースについて同じレベルのアクティビティを監査するように設定されているとします。次に、`myuser` ユーザーを監査しないことにします。次の SQL コマンドを使用して、`myuser` の監査機能を無効にできます。

```
ALTER USER myuser SET pgaudit.log TO 'NONE';
```

次に、次のクエリを使用して `pgaudit.log` の `user_specific_settings` 列をチェックし、パラメータが `NONE` に設定されていることを確認できます。

```
SELECT
    usename AS user_name,
    useconfig AS user_specific_settings
FROM
    pg_user
WHERE
    usename = 'myuser';
```

次のような出力が表示されます。

```
 user_name | user_specific_settings
-----------+------------------------
 myuser    | {pgaudit.log=NONE}
(1 row)
```

次のコマンドを使用すると、データベースとのセッションの最中に、指定したユーザーのログをオフにできます。

```
ALTER USER myuser IN DATABASE mydatabase SET pgaudit.log TO 'none';
```

次のクエリを使用して、特定のユーザーとデータベースの組み合わせの pgaudit.log の設定列を確認します。

```
SELECT
    usename AS "user_name",
    datname AS "database_name",
    pg_catalog.array_to_string(setconfig, E'\n') AS "settings"
FROM
    pg_catalog.pg_db_role_setting s
    LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase
    LEFT JOIN pg_catalog.pg_user r ON r.usesysid = setrole
WHERE
    usename = 'myuser'
    AND datname = 'mydatabase'
ORDER BY
    1,
    2;
```

以下のような出力が表示されます。

```
  user_name | database_name |     settings
-----------+---------------+------------------
 myuser    | mydatabase    | pgaudit.log=none
(1 row)
```

`myuser` の監査を無効化した後に、`mydatabase` の変更を追跡しないことにしました。次のコマンドを使用して、その特定のデータベースの監査を無効化します。

```
ALTER DATABASE mydatabase SET pgaudit.log to 'NONE';
```

次に、以下のクエリで database\$1specific\$1settings 列を確認し、pgaudit.log が NONE に設定されていることを確認します。

```
SELECT
a.datname AS database_name,
b.setconfig AS database_specific_settings
FROM
pg_database a
FULL JOIN pg_db_role_setting b ON a.oid = b.setdatabase
WHERE
a.datname = 'mydatabase';
```

次のような出力が表示されます。

```
 database_name | database_specific_settings
---------------+----------------------------
 mydatabase    | {pgaudit.log=NONE}
(1 row)
```

myuser の設定をデフォルト設定に戻すには、次のコマンドを使用します。

```
ALTER USER myuser RESET pgaudit.log;
```

設定をデータベースのデフォルト設定に戻すには、次のコマンドを使用します。

```
ALTER DATABASE mydatabase RESET pgaudit.log;
```

ユーザーとデータベースをデフォルト設定にリセットするには、次のコマンドを使用します。

```
ALTER USER myuser IN DATABASE mydatabase RESET pgaudit.log;
```

また、`pgaudit.log` パラメータに `pgaudit.log` を他の許容値のいずれかに設定することで、特定のイベントをログに記録することもできます 詳細については、「[`pgaudit.log` パラメータの許容設定のリスト](Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.md#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings)」を参照してください。

```
ALTER USER myuser SET pgaudit.log TO 'read';
ALTER DATABASE mydatabase SET pgaudit.log TO 'function';
ALTER USER myuser IN DATABASE mydatabase SET pgaudit.log TO 'read,function'
```

# pgAudit 拡張機能のリファレンス
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference"></a>

このセクションにリストされている 1 つまたは複数のパラメータを変更することで、監査ログに必要な詳細レベルを指定できます。

## pgAudit 動作の制御
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.basic-setup.parameters"></a>

監査ログは、次のテーブルに示す 1 つ以上のパラメータを変更することで制御できます。


| パラメータ | 説明 | 
| --- | --- | 
| `pgaudit.log`  | セッション監査ログ記録によってログに記録されるステートメントのクラスを指定します。許容値には、ddl、関数、その他、読み取り、ロール、書き込み、なし、すべてが含まれます。(詳しくは、「[`pgaudit.log` パラメータの許容設定のリスト](#Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings)」を参照してください)。 | 
| `pgaudit.log_catalog` | オンにすると (1 に設定)、ステートメント内のすべてのリレーションが pg\$1catalog 内にある場合に、ステートメントを監査証跡に追加します。 | 
| `pgaudit.log_level` | ログエントリに使用されるログレベルを指定します。指定できる値は debug5、debug4、debug3、debug2、debug1、info、notice、warning、log です。 | 
| `pgaudit.log_parameter` | オン (1 に設定) すると、ステートメントとともに渡されたパラメータが監査ログに記録されます。 | 
| `pgaudit.log_relation` | オンにすると (1 に設定)、セッションの監査ログで、SELECT ステートメントまたは DML ステートメントで参照されるリレーション (TABLE、VIEW など) ごとに個別のログエントリが作成されます。 | 
| `pgaudit.log_statement_once` | ログ記録に、ステートメントテキストとパラメータを、ステートメントとサブステートメントの組み合わせの最初のログエントリとともに含めるか、すべてのエントリとともに含めるかを指定します。 | 
| `pgaudit.role` | オブジェクト監査ログ記録に使用するマスターロールを指定します。唯一許容されるエントリは `rds_pgaudit` です。 | 

## `pgaudit.log` パラメータの許容設定のリスト
<a name="Appendix.PostgreSQL.CommonDBATasks.pgaudit.reference.pgaudit-log-settings"></a>

 


| 値 | 説明 | 
| --- | --- | 
| なし | これがデフォルトです。データベースの変更は記録されません。 | 
| すべて | すべてをログに記録します (読み取り、書き込み、関数、ロール、DDL、その他)。 | 
| ddl | `ROLE` クラスに含まれていない、すべてのデータ定義言語 (DDL) ステートメントのログ記録。 | 
| 関数 | 関数呼び出し、および `DO` ブロックのログ記録。 | 
| misc | `DISCARD`、`FETCH`、`CHECKPOINT`、`VACUUM`、`SET` など、さまざまなコマンドのログ記録。 | 
| 読む | `SELECT` および `COPY` のログ記録 (ソースがリレーション (テーブルなどの) またはクエリの場合)。 | 
| ロール | `GRANT`、`REVOKE`、`CREATE ROLE`、`ALTER ROLE`、`DROP ROLE` など、ロールと権限に関連するステートメントのログ記録。 | 
| 書き込み | `INSERT`、`UPDATE`、`DELETE`、`TRUNCATE`、および `COPY` のログ記録 (送信先がリレーションの場合)。 | 

セッション監査で複数のイベントタイプをログ記録するには、カンマ区切りリストを使用します。すべてのイベントタイプをログ記録するには、`pgaudit.log` を `ALL` に設定します。DB インスタンスを再起動して、変更を適用します。

オブジェクト監査では、監査のログ記録を絞り込み、特定のリレーションを操作できます。例えば、1 つまたは複数のテーブルで、`READ` オペレーションのログ記録を監査するよう指定できます。

# PostgreSQL pg\$1cron エクステンションによるメンテナンスのスケジューリング
<a name="PostgreSQL_pg_cron"></a>

PostgreSQL `pg_cron` エクステンションを使用すると、PostgreSQL データベース内でメンテナンスコマンドのスケジュールを組むことができます。拡張機能の詳細については、pg\$1cron ドキュメントの 「[What is pg\$1cron?](https://github.com/citusdata/pg_cron)」 を参照してください。

`pg_cron` エクステンションは PostgreSQL の RDS エンジンのバージョン 12.5 以降でサポートされています。

`pg_cron` の使用の詳細については、「[RDS for PostgreSQL または Aurora PostgreSQL 互換エディションのデータベースで pg\$1cron を使用してジョブをスケジュールする](https://aws.amazon.com/blogs/database/schedule-jobs-with-pg_cron-on-your-amazon-rds-for-postgresql-or-amazon-aurora-for-postgresql-databases/)」を参照してください

**注記**  
`pg_cron` 拡張機能バージョンは、pg\$1available\$1extensions ビューに 1.6 などの 2 桁のバージョンとして表示されます。1.6.4 や 1.6.5 などの 3 桁のバージョンが表示される場合がありますが、一部のコンテキストでは、拡張機能のアップグレードを実行するときに 2 桁のバージョンを指定する必要があります。

**Topics**
+ [pg\$1cron 拡張機能のセットアップ](#PostgreSQL_pg_cron.enable)
+ [データベースユーザーに pg\$1cron を使用する権限を付与する](#PostgreSQL_pg_cron.permissions)
+ [pg\$1cron ジョブのスケジューリング](#PostgreSQL_pg_cron.examples)
+ [pg\$1cron 拡張機能のリファレンス](#PostgreSQL_pg_cron.reference)

## pg\$1cron 拡張機能のセットアップ
<a name="PostgreSQL_pg_cron.enable"></a>

次のように `pg_cron` 拡張機能をセットアップします。

1. `shared_preload_libraries` パラメータ値に `pg_cron` を追加して、PostgreSQL DB インスタンスに関連付けられているカスタムパラメータグループを変更します。
   + RDS for PostgreSQL DB インスタンスが `rds.allowed_extensions` パラメータを使用して、インストール可能な拡張機能を明示的に一覧表示するには、リストに `pg_cron` 拡張機能を追加する必要があります。RDS for PostgreSQL の特定のバージョンのみが、`rds.allowed_extensions` パラメータに対応しています。デフォルトでは使用可能なすべての拡張機能が許可されます。詳しくは、「[PostgreSQL エクステンションのインストールを制限する](PostgreSQL.Concepts.General.FeatureSupport.Extensions.md#PostgreSQL.Concepts.General.FeatureSupport.Extensions.Restriction)」を参照してください。

   静的パラメータグループの変更を反映するために PostgreSQL DB インスタンスを再起動します。パラメータグループを使用する方法の詳細については、[Amazon RDS の DB パラメータグループのパラメータの変更](USER_WorkingWithParamGroups.Modifying.md) を参照してください。

1. PostgreSQL DB インスタンスが再起動したら、`rds_superuser` の許可を持つアカウントを使用して以下のコマンドを実行します。例えば、RDS for PostgreSQL DB インスタンスの作成時にデフォルト設定を使用した場合は、ユーザー `postgres` として接続し拡張機能を作成します。

   ```
   CREATE EXTENSION pg_cron;
   ```

   `pg_cron` スケジューラは、`postgres` という名前のデフォルトの PostgreSQL データベースに設定されます。`pg_cron` オブジェクトはこの `postgres` データベースに作成され、すべてのスケジューリングアクションがこのデータベースで実行されます。

1. デフォルト設定を使用することも、ジョブをスケジュールして、PostgreSQL DB インスタンス内の他のデータベースで実行させることもできます。PostgreSQL DB インスタンス内の他のデータベースでジョブをスケジュールするには、[デフォルトのデータベース以外のデータベースでの cron ジョブのスケジューリング](#PostgreSQL_pg_cron.otherDB) の例を参照してください。

## データベースユーザーに pg\$1cron を使用する権限を付与する
<a name="PostgreSQL_pg_cron.permissions"></a>

`pg_cron` 拡張機能をインストールするには、`rds_superuser` 権限が必要です。ただし、`pg_cron` の使用権限は (`rds_superuser` グループ/ロールのメンバーによって) 他のデータベースユーザーに付与して、各ユーザーが自分のジョブをスケジュールできるようにすることができます。本番環境での運用が改善される場合にのみ、`cron` スキーマへのアクセス許可を付与することをお勧めします。

`cron` スキーマでデータベースユーザー権限を付与するには、以下のコマンドを実行します。

```
postgres=> GRANT USAGE ON SCHEMA cron TO db-user;
```

これにより、アクセス権限のあるオブジェクトの cron ジョブをスケジュールするための `cron` スキーマへの *db-user* アクセス許可が付与されます。データベースユーザーに権限がない場合、以下に示すように、エラーメッセージを `postgresql.log` ファイルに投稿した後にジョブは失敗します。

```
2020-12-08 16:41:00 UTC::@:[30647]:ERROR: permission denied for table table-name
2020-12-08 16:41:00 UTC::@:[27071]:LOG: background worker "pg_cron" (PID 30647) exited with exit code 1
```

つまり、`cron` スキーマへの権限を付与されているデータベースユーザーに、スケジュールを設定する予定のオブジェクト (テーブル、スキーマなど) に対する権限も付与されていることを確認します。

この cron ジョブの詳細と、その成功または失敗も `cron.job_run_details` テーブルにキャプチャされます。詳細については、「[ジョブのスケジュール設定とステータス取得用のテーブル](#PostgreSQL_pg_cron.tables)」を参照してください。

## pg\$1cron ジョブのスケジューリング
<a name="PostgreSQL_pg_cron.examples"></a>

次のセクションでは、`pg_cron` ジョブを使用してさまざまな管理タスクをスケジュールする方法について説明します。

**注記**  
`pg_cron` ジョブの作成時は、`max_worker_processes` 設定が `cron.max_running_jobs` の数より大きいことを確認します。バックグラウンドのワーカープロセスを使い切ると、`pg_cron` ジョブは失敗します。`pg_cron` ジョブのデフォルト数は `5` です。詳しくは、「[pg\$1cron 拡張機能の管理用パラメータ](#PostgreSQL_pg_cron.parameters)」を参照してください。

**Topics**
+ [テーブルのバキューム処理](#PostgreSQL_pg_cron.vacuum)
+ [pg\$1cron の履歴テーブルの除去](#PostgreSQL_pg_cron.job_run_details)
+ [エラーのログを postgresql.log ファイルにのみ記録する](#PostgreSQL_pg_cron.log_run)
+ [デフォルトのデータベース以外のデータベースでの cron ジョブのスケジューリング](#PostgreSQL_pg_cron.otherDB)

### テーブルのバキューム処理
<a name="PostgreSQL_pg_cron.vacuum"></a>

Autovacuum は、ほとんどの場合、バキュームのメンテナンスを実行します。ただし、特定のテーブルのバキューム処理を、選択した特定の時点にスケジュールしたい、というケースも考えられます。

「[Amazon RDS for PostgreSQL での PostgreSQL 自動バキュームの使用](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)」も参照してください。

以下は、`cron.schedule` 関数を使用して、毎日 22:00 (GMT) に特定のテーブルで `VACUUM FREEZE` を使用するようにジョブをセットアップする例です。

```
SELECT cron.schedule('manual vacuum', '0 22 * * *', 'VACUUM FREEZE pgbench_accounts');
 schedule
----------
1
(1 row)
```

上記の例を実行した後、次のように `cron.job_run_details` テーブル内の履歴を確認できます。

```
postgres=> SELECT * FROM cron.job_run_details;
jobid  | runid | job_pid | database | username | command                        | status    | return_message | start_time                    | end_time
-------+-------+---------+----------+----------+--------------------------------+-----------+----------------+-------------------------------+-------------------------------
 1     | 1     | 3395    | postgres | adminuser| vacuum freeze pgbench_accounts | succeeded | VACUUM         | 2020-12-04 21:10:00.050386+00 | 2020-12-04 21:10:00.072028+00
(1 row)
```

失敗したジョブを確認するための `cron.job_run_details` テーブルのクエリは、次のとおりです。

```
postgres=> SELECT * FROM cron.job_run_details WHERE status = 'failed';
jobid | runid | job_pid | database | username | command                       | status | return_message                                   | start_time                    | end_time
------+-------+---------+----------+----------+-------------------------------+--------+--------------------------------------------------+-------------------------------+------------------------------
 5    | 4     | 30339   | postgres | adminuser| vacuum freeze pgbench_account | failed | ERROR: relation "pgbench_account" does not exist | 2020-12-04 21:48:00.015145+00 | 2020-12-04 21:48:00.029567+00
(1 row)
```

詳細については、「[ジョブのスケジュール設定とステータス取得用のテーブル](#PostgreSQL_pg_cron.tables)」を参照してください。

### pg\$1cron の履歴テーブルの除去
<a name="PostgreSQL_pg_cron.job_run_details"></a>

`cron.job_run_details` テーブルには、時間の経過とともに非常に大きくなる可能性がある cron ジョブの履歴が含まれています。そのため、このテーブルをクリアにするジョブをスケジュールすることをお勧めします。例えば、トラブルシューティングの目的では、1 週間分のエントリを保持するだけで十分です。

次の例では、[cron.schedule](#PostgreSQL_pg_cron.schedule) 関数を使用して、`cron.job_run_details` テーブルをクリアにするよう、毎日午前 0 時に実行されるジョブをスケジュールします。このジョブは過去 7 日間しか残せません。`rds_superuser` アカウントを使用して、以下のようなジョブをスケジュールできます。

```
SELECT cron.schedule('0 0 * * *', $$DELETE 
    FROM cron.job_run_details 
    WHERE end_time < now() - interval '7 days'$$);
```

(詳しくは、「[ジョブのスケジュール設定とステータス取得用のテーブル](#PostgreSQL_pg_cron.tables)」を参照してください。)

### エラーのログを postgresql.log ファイルにのみ記録する
<a name="PostgreSQL_pg_cron.log_run"></a>

`cron.job_run_details` テーブルへの書き込みをしないようにするには、PostgreSQL DB インスタンスに関連付けられているパラメータグループを変更し、`cron.log_run` パラメータをオフに設定します。`pg_cron` 拡張機能によって対象のテーブルには書き込まなくなり、エラーは `postgresql.log` ファイルのみに記録されるようになります。詳細については、「[Amazon RDS の DB パラメータグループのパラメータの変更](USER_WorkingWithParamGroups.Modifying.md)」を参照してください。

`cron.log_run` パラメータの値を確認するには、次のコマンドを使用します。

```
postgres=> SHOW cron.log_run;
```

詳細については、「[pg\$1cron 拡張機能の管理用パラメータ](#PostgreSQL_pg_cron.parameters)」を参照してください。

### デフォルトのデータベース以外のデータベースでの cron ジョブのスケジューリング
<a name="PostgreSQL_pg_cron.otherDB"></a>

`pg_cron` のメタデータはすべて、`postgres` という名前の PostgreSQL のデフォルトのデータベースに保持されます。メンテナンスの cron ジョブの実行にはバックグラウンドワーカーが使用されるため、PostgreSQL DB インスタンス内の任意のデータベースでジョブのスケジューリングが可能です。

**注記**  
`rds_superuser` ロールまたは `rds_superuser` 権限を持つユーザーのみが、データベース内のすべての cron ジョブを一覧表示できます。他のユーザーは、自分のジョブのみを `cron.job` テーブルに表示できます。

1. cron データベースで、[cron.schedule](#PostgreSQL_pg_cron.schedule) を使用して通常どおりにジョブをスケジュールします。

   ```
   postgres=> SELECT cron.schedule('database1 manual vacuum', '29 03 * * *', 'vacuum freeze test_table');
   ```

1. 作成したジョブのデータベース列を、`rds_superuser` ロールを持つユーザーとして更新し、そのジョブを PostgreSQL DB インスタンス内の別のデータベースで実行できるようにします。

   ```
   postgres=> UPDATE cron.job SET database = 'database1' WHERE jobid = 106;
   ```

1.  `cron.job` テーブルのクエリを実行して確認します。

   ```
   postgres=> SELECT * FROM cron.job;
   jobid | schedule    | command                        | nodename  | nodeport | database | username  | active | jobname
   ------+-------------+--------------------------------+-----------+----------+----------+-----------+--------+-------------------------
   106   | 29 03 * * * | vacuum freeze test_table       | localhost | 8192     | database1| adminuser | t      | database1 manual vacuum
     1   | 59 23 * * * | vacuum freeze pgbench_accounts | localhost | 8192     | postgres | adminuser | t      | manual vacuum
   (2 rows)
   ```

**注記**  
状況によっては、別のデータベースで実行する cron ジョブを追加することがあります。このような場合、ジョブは、正しいデータベース列を更新する前に、デフォルトのデータベース (`postgres`) で実行しようとする可能性があります。ユーザー名に権限がある場合、デフォルトのデータベースでジョブが正常に実行されます。

## pg\$1cron 拡張機能のリファレンス
<a name="PostgreSQL_pg_cron.reference"></a>

`pg_cron` エクステンションでは、次のパラメータ、関数、およびテーブルを使用できます。詳細については、pg\$1cron ドキュメントの [What is pg\$1cron?](https://github.com/citusdata/pg_cron) を参照してください。

**Topics**
+ [pg\$1cron 拡張機能の管理用パラメータ](#PostgreSQL_pg_cron.parameters)
+ [関数リファレンス: cron.schedule](#PostgreSQL_pg_cron.schedule)
+ [関数リファレンス: cron.unschedule](#PostgreSQL_pg_cron.unschedule)
+ [ジョブのスケジュール設定とステータス取得用のテーブル](#PostgreSQL_pg_cron.tables)

### pg\$1cron 拡張機能の管理用パラメータ
<a name="PostgreSQL_pg_cron.parameters"></a>

`pg_cron` エクステンションの動作を制御するパラメータの一覧を次に示します。


| Parameter | 説明 | 
| --- | --- | 
| cron.database\$1name |  `pg_cron` メタデータが保持されるデータベース。  | 
| cron.host |  PostgresSQL に接続するためのホスト名。この値は変更できません。  | 
| cron.log\$1run |  `job_run_details` テーブルで実行されるすべてのジョブをログに記録します。有効な値は `on` または `off` です。詳細については、「[ジョブのスケジュール設定とステータス取得用のテーブル](#PostgreSQL_pg_cron.tables)」を参照してください。  | 
| cron.log\$1statement |  実行する前に、すべての cron ステートメントを記録します。有効な値は `on` または `off` です。  | 
| cron.max\$1running\$1jobs |  同時に実行できるジョブの最大数。  | 
| cron.use\$1background\$1workers |  クライアントセッションの代わりにバックグラウンドワーカーを使用します。この値は変更できません。  | 

次の SQL コマンドを使用して、これらのパラメータとその値を表示します。

```
postgres=> SELECT name, setting, short_desc FROM pg_settings WHERE name LIKE 'cron.%' ORDER BY name;
```

### 関数リファレンス: cron.schedule
<a name="PostgreSQL_pg_cron.schedule"></a>

この関数は、cron ジョブをスケジュールします。このジョブは、デフォルトの `postgres` データベースで初期にスケジュールされます。この関数は、ジョブ識別子を表す `bigint` の値を返します。PostgreSQL DB インスタンス内の他のデータベースで実行するようにジョブをスケジュールするには、[デフォルトのデータベース以外のデータベースでの cron ジョブのスケジューリング](#PostgreSQL_pg_cron.otherDB) の例を参照してください。

この関数には、2 つの構文形式があります。

**構文**  

```
cron.schedule (job_name,
    schedule,
    command
);

cron.schedule (schedule,
    command
);
```

**パラメータ**      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html)

**例**  

```
postgres=> SELECT cron.schedule ('test','0 10 * * *', 'VACUUM pgbench_history');
 schedule
----------
      145
(1 row)

postgres=> SELECT cron.schedule ('0 15 * * *', 'VACUUM pgbench_accounts');
 schedule
----------
      146
(1 row)
```

### 関数リファレンス: cron.unschedule
<a name="PostgreSQL_pg_cron.unschedule"></a>

この関数は、cron ジョブを削除します。`job_name` または `job_id` を指定できます。ポリシーにより、ユーザーがジョブのスケジュールを削除する所有者であることが確認されます。この関数は、成功または失敗を示すブール値を返します。

関数の構文形式は以下のとおりです。

**構文**  

```
cron.unschedule (job_id);

cron.unschedule (job_name);
```

**パラメータ**      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html)

**例**  

```
postgres=> SELECT cron.unschedule(108);
 unschedule
------------
 t
(1 row)

postgres=> SELECT cron.unschedule('test');
 unschedule
------------
 t
(1 row)
```

### ジョブのスケジュール設定とステータス取得用のテーブル
<a name="PostgreSQL_pg_cron.tables"></a>

以下のテーブルは、cron ジョブのスケジューリングのためと、そのジョブがどのように完了したかを記録するために使用されます。


| 表 | 説明 | 
| --- | --- | 
| cron.job |  スケジュールされた各ジョブに関するメタデータが含まれます。このテーブルとのほとんどのやり取りは、`cron.schedule` 関数および `cron.unschedule` 関数を使用して行う必要があります。  更新または挿入の権限をこのテーブルに直接与えないようにお勧めします。そうすることで、ユーザーは `username` 列を更新し、`rds-superuser` として実行できるようになります。   | 
| cron.job\$1run\$1details |  ここには、過去にスケジュールされ実行されたジョブに関する履歴の情報が含まれます。これは、実行されたジョブのステータス、返されたメッセージ、およびスタートと終了の時間を調査する場合に便利です。  このテーブルが無期限に増えないようにするには、定期的に削除してください。例については、「[pg\$1cron の履歴テーブルの除去](#PostgreSQL_pg_cron.job_run_details)」を参照してください。   | 

# pglogical を使用してインスタンス間でデータを同期する
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical"></a>

現在利用可能なすべての RDS for PostgreSQL バージョンは、`pglogical` 拡張機能をサポートしています。pglogical 拡張は、バージョン 10 で PostgreSQL により導入された機能的に類似した論理レプリケーション機能よりも前のものです。詳細については、「[Amazon RDS for PostgreSQL の論理レプリケーションの実行](PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.md)」を参照してください。

`pglogical` 拡張が、2 つ以上の 間の論理レプリケーションをサポートします。RDS for PostgreSQL DB インスタンス。また、異なる PostgreSQL バージョン間のレプリケーション、および RDS for PostgreSQL DB と Aurora PostgreSQL DB クラスターで実行されているデータベース間のレプリケーションもサポートしています。`pglogical` 拡張は、公開/サブスクライブモデルを使用して、テーブルやその他のオブジェクト (シーケンスなど) への変更をパブリッシャーからサブスクライバーに複製します。パブリッシャーノードからサブスクライバーノードに変更が確実に同期されるようにするには、レプリケーションスロットを使用し、次のように定義されます。
+ *パブリッシャーノード*は、他のノードにレプリケートされるデータのソースである RDS for PostgreSQL DB インスタンスです。パブリッシャーノードは、パブリケーションセットでレプリケートするテーブルを定義します。
+ *サブスクライバーノード*は、公開者から WAL の更新を受け取る RDS for PostgreSQL DB インスタンスです。サブスクライバーは、パブリッシャーに接続してデコードされた WAL データを取得するためのサブスクリプションを作成します。サブスクライバーがサブスクリプションを作成すると、パブリッシャーノードに複製スロットが作成されます。

`pglogical` 拡張の設定についての情報は、以下を参照してください。

**Topics**
+ [pglogical 拡張の要件と制限](#Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations)
+ [pglogical 拡張のセットアップ](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)
+ [RDS for PostgreSQL DB インスタンスに論理レプリケーションを設定する](Appendix.PostgreSQL.CommonDBATasks.pglogical.setup-replication.md)
+ [メジャーアップグレード後の論理レプリケーションの再確立](Appendix.PostgreSQL.CommonDBATasks.pglogical.recover-replication-after-upgrade.md)
+ [RDS for PostgreSQL 用ロジカルレプリケーションスロットの管理](Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots.md)
+ [pglogical 拡張のパラメータリファレンス](Appendix.PostgreSQL.CommonDBATasks.pglogical.reference.md)

## pglogical 拡張の要件と制限
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations"></a>

RDS for PostgreSQL の現在利用可能なすべてのリリースが `pglogical` 拡張機能をサポートしています。

パブリッシャーノードとサブスクライバーノードの両方を論理レプリケーション用に設定する必要があります。

サブスクライバーからパブリッシャーにレプリケートするテーブルは、同じ名前と同じスキーマである必要があります。これらのテーブルにも同じ列が含まれている必要があり、列は同じデータ型を使用する必要があります。パブリッシャーテーブルとサブスクライバーテーブルの両方に同じプライマリキーが必要です。一意の制約事項としては PRIMARY KEY のみを使用することをお勧めします。

サブスクライバーノードのテーブルには、CHECK 制約と NOT NULL 制約について、パブリッシャーノードのテーブルよりも許可度が高い制約を設定できます。

`pglogical` 拡張は、PostgreSQL (バージョン 10 以降) に組み込まれている論理レプリケーション機能ではサポートされていない双方向レプリケーションなどの機能を提供します。詳細については、「[PostgreSQL bi-directional replication using pglogical](https://aws.amazon.com/blogs/database/postgresql-bi-directional-replication-using-pglogical/)」(pglogical を使用した PostgreSQL の双方向レプリケーション) を参照してください。

# pglogical 拡張のセットアップ
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup"></a>

RDS for PostgreSQL DB インスタンスに `pglogical` 拡張機能を設定するには、RDS for PostgreSQL DB インスタンスのカスタム DB パラメータグループの共有ライブラリに `pglogical` を追加します。また、論理デコードをオンにするには、`rds.logical_replication` パラメータの値を `1` に設定する必要があります。最後に、データベースに拡張を作成します。これらのタスクには、AWS マネジメントコンソール または AWS CLI を使用できます。

これらのタスクを実行するには、`rds_superuser` ロールとしてアクセス許可が必要です。

以下のステップでは、 RDS for PostgreSQL DB インスタンスがカスタム DB パラメータグループに関連付けられていることを前提としています。カスタム DB パラメータグループの作成については、「[Amazon RDS のパラメータグループ](USER_WorkingWithParamGroups.md)」を参照してください。

## コンソール
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CON"></a>

**pglogical 拡張をセットアップするには**

1. AWS マネジメントコンソール にサインインし、Amazon RDS コンソール ([https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)) を開きます。

1. ナビゲーションペインで、 RDS for PostgreSQL DB インスタンスを選択します。

1. の **[Configuration]** (設定) タブを開きます。RDS for PostgreSQL DB インスタンス。インスタンスの詳細の中から、**パラメータグループ**のリンクを見つけてください。

1. リンクを選択して、に関連するカスタムパラメータを開きます。RDS for PostgreSQL DB インスタンス。

1. **パラメータ**検索フィールドに、`shared_pre` を入力して `shared_preload_libraries` パラメータを検索します。

1. プロパティ値にアクセスするには、**[Edit parameters]** (パラメータの編集) を選択します。

1. **[Values]** (値) フィールドのリストに `pglogical` を追加します。値のリスト内の項目を区切るにはカンマを使用します。  
![\[pglogical が追加された shared_preload_libraries パラメータの画像。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pglogical.png)

1. `rds.logical_replication` パラメータを見つけて `1` に設定し、論理レプリケーションをオンにします。

1. RDS for PostgreSQL DB インスタンス を再起動して、変更を有効にします。

1. インスタンスが使用可能になったら、`psql` (または pgAdmin) を使用して RDS for PostgreSQL DB インスタンスに接続します。

   ```
   psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
   ```

1. pglogical が初期化されていることを確認するには、次のコマンドを実行します。

   ```
   SHOW shared_preload_libraries;
   shared_preload_libraries 
   --------------------------
   rdsutils,pglogical
   (1 row)
   ```

1. 次のように、論理デコードを有効にする設定を確認します。

   ```
   SHOW wal_level;
   wal_level
   -----------
    logical
   (1 row)
   ```

1. 次のように拡張を作成します。

   ```
   CREATE EXTENSION pglogical;
   EXTENSION CREATED
   ```

1. **[Save changes]** (変更の保存) をクリックします。

1. Amazon RDS コンソール ([https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)) を開きます。

1. データベースリストから RDS for PostgreSQL DB インスタンス を選択して選択し、アクションメニューから **[Reboot]** (再起動) を選択します。

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CLI"></a>

**pglogical 拡張のセットアップするには**

AWS CLI を使用して pglogical を設定するには、次の手順に示すように、[modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) オペレーションを呼び出してカスタムパラメータグループの特定のパラメータを変更します。

1. 次の AWS CLI コマンドを使用して`shared_preload_libraries`パラメータに `pglogical` を追加します。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=pglogical,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 次の AWS CLI コマンドを使用して `rds.logical_replication` を `1` に設定し、の論理デコード機能をオンにします。RDS for PostgreSQL DB インスタンス。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=rds.logical_replication,ParameterValue=1,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 次の AWS CLI コマンドを使用して RDS for PostgreSQL DB インスタンスを再起動し、pglogical ライブラリを初期化します。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. インスタンスが使用可能になったら、`psql` を使用して RDS for PostgreSQL DB インスタンスに接続します。

   ```
   psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
   ```

1. 次のように拡張を作成します。

   ```
   CREATE EXTENSION pglogical;
   EXTENSION CREATED
   ```

1. 次の AWS CLI コマンドを使用して、 RDS for PostgreSQL DB インスタンスを再起動します。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

# RDS for PostgreSQL DB インスタンスに論理レプリケーションを設定する
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.setup-replication"></a>

以下の手順では、2 つの RDS for PostgreSQL DB インスタンス間で論理レプリケーションを開始する方法を示しています。これらのステップでは、ソース (パブリッシャー) とターゲット (サブスクライバー) の両方に、[pglogical 拡張のセットアップ](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md) で説明されているように `pglogical` 拡張が設定されていることを前提としています。

**注記**  
サブスクライバーノードの `node_name` は、`rds` で開始することができません。

**パブリッシャーノードを作成し、複製するテーブルを定義するには**

これらのステップは、別のノードに複製する 1 つ以上のテーブルがあるデータベースが RDS for PostgreSQL インスタンスにあることを前提としています。サブスクライバー上のパブリッシャーからテーブル構造を再作成する必要があるため、まず必要に応じてテーブル構造を取得します。そのためには、`psql` メタコマンド `\d tablename` を使用してサブスクライバーインスタンスに同じテーブルを作成します。次の手順では、デモンストレーションを目的として、パブリッシャー (ソース) でサンプルテーブルを作成します。

1. `psql` を使用して、サブスクライバーのソースとして使用したいテーブルがあるインスタンスに接続します。

   ```
   psql --host=source-instance.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
   ```

   複製する既存のテーブルがない場合は、次のようにサンプルテーブルを作成できます。

   1. 次の SQL ステートメントを使用してサンプルテーブルを作成します。

      ```
      CREATE TABLE docs_lab_table (a int PRIMARY KEY);
      ```

   1. 次の SQL ステートメントを使用して、生成されたデータをテーブルに入力します。

      ```
      INSERT INTO docs_lab_table VALUES (generate_series(1,5000));
      INSERT 0 5000
      ```

   1. 次の SQL ステートメントを使用して、テーブルにデータが存在することを確認します。

      ```
      SELECT count(*) FROM docs_lab_table;
      ```

1. 次のように、この RDS for PostgreSQL DB インスタンスをパブリッシャーノードとして指定します。

   ```
   SELECT pglogical.create_node(
       node_name := 'docs_lab_provider',
       dsn := 'host=source-instance.aws-region.rds.amazonaws.com port=5432 dbname=labdb');
    create_node
   -------------
      3410995529
   (1 row)
   ```

1. 複製するテーブルをデフォルトのレプリケーションセットに追加します。レプリケーションセットの詳細については、pglogical ドキュメントの「[Replication sets](https://github.com/2ndQuadrant/pglogical/tree/REL2_x_STABLE/docs#replication-sets)」(レプリケーションセット) を参照してください。

   ```
   SELECT pglogical.replication_set_add_table('default', 'docs_lab_table', 'true', NULL, NULL);
    replication_set_add_table
     ---------------------------
     t
     (1 row)
   ```

パブリッシャーノードの設定が完了しました。これで、パブリッシャーから更新を受け取るようにサブスクライバーノードを設定できます。

**サブスクライバーノードを設定し、更新を受信するサブスクリプションを作成するには**

これらのステップは、RDS for PostgreSQL DB インスタンスが `pglogical` 拡張機能を使用してセットアップされていることを前提としています。詳細については、「[pglogical 拡張のセットアップ](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)」を参照してください。

1. `psql` を使用して、パブリッシャーから更新を受け取るインスタンスに接続します。

   ```
   psql --host=target-instance.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
   ```

1. サブスクライバーの RDS for PostgreSQL DB インスタンスで、パブリッシャーに存在するのと同じテーブルを作成します。この例では、テーブルは `docs_lab_table` です。次に示すようにテーブルを作成できます。

   ```
   CREATE TABLE docs_lab_table (a int PRIMARY KEY);
   ```

1. このテーブルが空であることを確認します。

   ```
   SELECT count(*) FROM docs_lab_table;
    count
   -------
     0
   (1 row)
   ```

1. 次のように、この RDS for PostgreSQL DB インスタンスをサブスクライバーノードとして指定します。

   ```
   SELECT pglogical.create_node(
       node_name := 'docs_lab_target',
       dsn := 'host=target-instance.aws-region.rds.amazonaws.com port=5432 sslmode=require dbname=labdb user=postgres password=********');
    create_node
   -------------
      2182738256
   (1 row)
   ```

1. サブスクリプションを作成します。

   ```
   SELECT pglogical.create_subscription(
      subscription_name := 'docs_lab_subscription',
      provider_dsn := 'host=source-instance.aws-region.rds.amazonaws.com port=5432 sslmode=require dbname=labdb user=postgres password=*******',
      replication_sets := ARRAY['default'],
      synchronize_data := true,
      forward_origins := '{}' );  
    create_subscription
   ---------------------
   1038357190
   (1 row)
   ```

   このステップを完了すると、パブリッシャーのテーブルのデータが、サブスクライバーのテーブルに作成されます。このことを確認するには、次の SQL クエリを使用します。

   ```
   SELECT count(*) FROM docs_lab_table;
    count
   -------
     5000
   (1 row)
   ```

これ以降、パブリッシャーのテーブルに加えられた変更は、サブスクライバーのテーブルにレプリケートされます。

# メジャーアップグレード後の論理レプリケーションの再確立
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.recover-replication-after-upgrade"></a>

論理レプリケーションのパブリッシャーノードとして設定されている RDS for PostgreSQL DB インスタンスのメジャーバージョンアップグレードを実行する前に、アクティブではないものを含め、すべてのレプリケーションスロットを削除する必要があります。パブリッシャーノードからデータベーストランザクションを一時的に迂回させ、レプリケーションスロットを削除し、RDS for PostgreSQL DB インスタンスをアップグレードしてから、レプリケーションを再確立して再開することをお勧めします。

レプリケーションスロットはパブリッシャーノードでのみホストされます。論理レプリケーションシナリオの RDS for PostgreSQL サブスクライバーノードには削除するスロットはありませんが、パブリッシャーへのサブスクリプションを持つサブスクライバーノードとして指定されている間は、メジャーバージョンにアップグレードできません。RDS for PostgreSQL サブスクライバーノードをアップグレードする前に、サブスクリプションとノードを削除してください。詳細については、「[ RDS for PostgreSQL 用ロジカルレプリケーションスロットの管理](Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots.md)」を参照してください。

## 論理レプリケーションが中断されたことの確認
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.recover-replication-after-upgrade.identifying-the-issue"></a>

次のように、パブリッシャーノードまたはサブスクライバーノードのいずれかにクエリを実行することで、レプリケーションプロセスが中断されたことを確認できます。

**パブリッシャーノードを確認するには**
+ `psql` を使用してパブリッシャーノードに接続して、`pg_replication_slots` 関数をクエリします。active 列の値に注目します。通常は `t` (true) が返されます。これは、レプリケーションがアクティブであることを示します。クエリが`f` (false) を返す場合は、サブスクライバーへのレプリケーションが停止したことを示します。

  ```
  SELECT slot_name,plugin,slot_type,active FROM pg_replication_slots;
                      slot_name              |      plugin      | slot_type | active
  -------------------------------------------+------------------+-----------+--------
   pgl_labdb_docs_labcb4fa94_docs_lab3de412c | pglogical_output | logical   | f
  (1 row)
  ```

**サブスクライバーノードを確認するには**

サブスクライバーノードでは、3 つの異なる方法でレプリケーションのステータスを確認できます。
+ サブスクライバーノードの PostgreSQL ログを調べて、失敗のメッセージを見つけます。ログでは、次に示すように、終了コード 1 を含むメッセージで失敗が識別されます。

  ```
  2022-07-06 16:17:03 UTC::@:[7361]:LOG: background worker "pglogical apply 16404:2880255011" (PID 14610) exited with exit code 1
  2022-07-06 16:19:44 UTC::@:[7361]:LOG: background worker "pglogical apply 16404:2880255011" (PID 21783) exited with exit code 1
  ```
+ `pg_replication_origin` 関数をクエリします。次のように、`psql` を使用してサブスクライバーノード上のデータベースに接続し、`pg_replication_origin` 関数をクエリします。

  ```
  SELECT * FROM pg_replication_origin;
   roident | roname
  ---------+--------
  (0 rows)
  ```

  結果セットが空の場合は、レプリケーションが中断されたことを意味します。通常、次のような出力が表示されます。

  ```
     roident |                       roname
    ---------+----------------------------------------------------
           1 | pgl_labdb_docs_labcb4fa94_docs_lab3de412c
    (1 row)
  ```
+ 次の例に示すように、`pglogical.show_subscription_status` 関数をクエリします。

  ```
  SELECT subscription_name,status,slot_name FROM pglogical.show_subscription_status();
       subscription_name | status |              slot_name
  ---====----------------+--------+-------------------------------------
   docs_lab_subscription | down   | pgl_labdb_docs_labcb4fa94_docs_lab3de412c
  (1 row)
  ```

  この出力は、レプリケーションが中断されたことを示しています。そのステータスは `down` です。通常、出力にはステータスが `replicating` として表示されます。

論理レプリケーションプロセスが中断された場合は、次のステップに従ってレプリケーションを再確立できます。

**パブリッシャーノードとサブスクライバーノード間の論理レプリケーションを再確立するには**

レプリケーションを再確立するには、以下のステップで説明するように、まずサブスクライバーをパブリッシャーノードから切断し、次にサブスクリプションを再確立します。

1. 次のように `psql` を使用してサブスクライバーノードに接続します。

   ```
   psql --host=222222222222.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
   ```

1. `pglogical.alter_subscription_disable` 関数を使用してサブスクリプションを非アクティブ化します。

   ```
   SELECT pglogical.alter_subscription_disable('docs_lab_subscription',true);
    alter_subscription_disable
   ----------------------------
    t
   (1 row)
   ```

1. 以下のように、`pg_replication_origin` をクエリして、パブリッシャーノードの識別子を取得します。

   ```
   SELECT * FROM pg_replication_origin;
    roident |               roname
   ---------+-------------------------------------
          1 | pgl_labdb_docs_labcb4fa94_docs_lab3de412c
   (1 row)
   ```

1. 前のステップからの応答を `pg_replication_origin_create` コマンドに使用して、サブスクリプションが再確立されたときに使用できる識別子を割り当てます。

   ```
   SELECT pg_replication_origin_create('pgl_labdb_docs_labcb4fa94_docs_lab3de412c');
     pg_replication_origin_create
   ------------------------------
                               1
   (1 row)
   ```

1. 次の例のように、ステータスを `true` にして名前を渡し、サブスクリプションを有効にします。

   ```
   SELECT pglogical.alter_subscription_enable('docs_lab_subscription',true);
     alter_subscription_enable
   ---------------------------
    t
   (1 row)
   ```

ノードのステータスを確認します。ステータスはこの例のように `replicating` として表示されているはずです。

```
SELECT subscription_name,status,slot_name
  FROM pglogical.show_subscription_status();
             subscription_name |   status    |              slot_name
-------------------------------+-------------+-------------------------------------
 docs_lab_subscription         | replicating | pgl_labdb_docs_lab98f517b_docs_lab3de412c
(1 row)
```

パブリッシャーノード上のサブスクライバーのレプリケーションスロットのステータスを確認します。スロットの `active` 列は `t` (true) を返し、レプリケーションが再確立されたことを示します。

```
SELECT slot_name,plugin,slot_type,active
  FROM pg_replication_slots;
                    slot_name              |      plugin      | slot_type | active
-------------------------------------------+------------------+-----------+--------
 pgl_labdb_docs_lab98f517b_docs_lab3de412c | pglogical_output | logical   | t
(1 row)
```

# RDS for PostgreSQL 用ロジカルレプリケーションスロットの管理
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.handle-slots"></a>

論理レプリケーションシナリオでパブリッシャーノードとして機能している RDS for PostgreSQL DB インスタンスでメジャーバージョンアップグレードを実行する前に、インスタンスのレプリケーションスロットを削除する必要があります。メジャーバージョンアップグレードの事前確認プロセスにより、スロットが削除されるまでアップグレードを続行できないことが通知されます。

RDS for PostgreSQL DB インスタンスからスロットを削除するには、まずサブスクリプションを削除してからスロットを削除します。

`pglogical` 拡張を使用して作成されたレプリケーションスロットを特定するには、各データベースにログインしてノードの名前を取得します。サブスクライバーノードにクエリを実行すると、次の例に示すように、パブリッシャーノードとサブスクライバーノードの両方が出力されます。

```
SELECT * FROM pglogical.node;
node_id   |     node_name
------------+-------------------
 2182738256 | docs_lab_target
 3410995529 | docs_lab_provider
(2 rows)
```

次のクエリで、サブスクリプションの詳細を取得できます。

```
SELECT sub_name,sub_slot_name,sub_target
  FROM pglogical.subscription;
 sub_name |         sub_slot_name          | sub_target
----------+--------------------------------+------------
  docs_lab_subscription     | pgl_labdb_docs_labcb4fa94_docs_lab3de412c | 2182738256
(1 row)
```

これで、次のようにサブスクリプションを削除できます。

```
SELECT pglogical.drop_subscription(subscription_name := 'docs_lab_subscription');
 drop_subscription
-------------------
                 1
(1 row)
```

サブスクリプションを削除すると、ノードを削除できます。

```
SELECT pglogical.drop_node(node_name := 'docs-lab-subscriber');
 drop_node
-----------
 t
(1 row)
```

次のように、ノードが存在しないことを確認できます。

```
SELECT * FROM pglogical.node;
 node_id | node_name
---------+-----------
(0 rows)
```

# pglogical 拡張のパラメータリファレンス
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.reference"></a>

表には、`pglogical` 拡張に関連するパラメータがあります。`pglogical.conflict_log_level` や `pglogical.conflict_resolution` などのパラメータは、更新の競合を処理するために使用されます。パブリッシャーから変更をサブスクライブしているテーブルにローカルで変更を加えると、競合が発生する可能性があります。これ以外にも、競合は、双方向のレプリケーションや、複数のサブスクライバーが同じパブリッシャーからレプリケートする場合など、さまざまなシナリオで発生する可能性があります。詳細については、「[PostgreSQL bi-directional replication using pglogical](https://aws.amazon.com/blogs/database/postgresql-bi-directional-replication-using-pglogical/)」(pglogical を使用した PostgreSQL の双方向レプリケーション) を参照してください。


| パラメータ | 説明 | 
| --- | --- | 
| pglogical.batch\$1inserts | 可能であれば、バッチ挿入。デフォルトでは設定されていません。オンにする場合は「1」に、オフにする場合は「0」に変更します。 | 
| pglogical.conflict\$1log\$1level | 解決された競合のログ記録に使用するログレベルを設定します。サポートされている文字列値は、debug5、debug4、debug3、debug2、debug1、info、notice、warning、error、log、fatal、panic です。 | 
| pglogical.conflict\$1resolution | 競合が解決可能な場合に競合を解決するために使用するメソッドを設定します。サポートされている文字列値は、error、apply\$1remote、keep\$1local、last\$1update\$1wins、first\$1update\$1wins です。 | 
| pglogical.extra\$1connection\$1options | すべてのピアノード接続に追加する接続オプション。 | 
| pglogical.synchronous\$1commit | pglogical 固有の同期コミット値 | 
| pglogical.use\$1spi | 低レベル API の代わりに SPI (サーバープログラミングインターフェイス) を使用して変更を適用します。オンにする場合は「1」に、オフにする場合は「0」に設定します。SPI の詳細については、PostgreSQL ドキュメントの「[サーバープログラミングインターフェイス](https://www.postgresql.org/docs/current/spi.html)」を参照してください。 | 

# pgactive を使用したアクティブ/アクティブレプリケーションのサポート
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive"></a>

`pgactive` 拡張は、アクティブ/アクティブレプリケーションを使用して、複数の RDS for PostgreSQL データベースに対する書き込み操作をサポートおよび調整します。Amazon RDS for PostgreSQL は、次のバージョンの `pgactive` 拡張機能をサポートしています。
+ RDS for PostgreSQL バージョン 17.0 以降のバージョン
+ RDS for PostgreSQL 16.1 またはそれ以降の 16 バージョン
+ RDS for PostgreSQL 15.4-R2 以降のバージョン 15
+ RDS for PostgreSQL 14.10 以降のバージョン 14
+ RDS for PostgreSQL 13.13 以降のバージョン 13
+ RDS for PostgreSQL 12.17 以降のバージョン 12
+ RDS for PostgreSQL 11.22

**注記**  
レプリケーション設定に複数のデータベースに対する書き込み操作があると、競合が発生する可能性があります。詳細については、[アクティブ/アクティブレプリケーションの競合の処理](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts.md)を参照してください。

**Topics**
+ [pgactive 拡張の制限事項](#Appendix.PostgreSQL.CommonDBATasks.pgactive.requirements-limitations)
+ [pgactive 拡張機能の初期化](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)
+ [RDS for PostgreSQL DB インスタンスのアクティブ/アクティブレプリケーションの設定](Appendix.PostgreSQL.CommonDBATasks.pgactive.setup-replication.md)
+ [pgactive メンバー間のレプリケーションラグの測定](Appendix.PostgreSQL.CommonDBATasks.pgactive.replicationlag.md)
+ [pgactive 拡張機能のパラメータ設定](Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.md)
+ [アクティブ/アクティブ競合について](Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.replication.md)
+ [pgactive スキーマについて](Appendix.PostgreSQL.CommonDBATasks.pgactive.schema.md)
+ [pgactive 関数リファレンス](pgactive-functions-reference.md)
+ [アクティブ/アクティブレプリケーションの競合の処理](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts.md)
+ [アクティブ/アクティブレプリケーションでのシーケンスの処理](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences.md)

## pgactive 拡張の制限事項
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.requirements-limitations"></a>
+ すべてのテーブルには主キーが必要です。主キーがないと、更新や削除は許可されません。主キー列の値は更新しないでください。
+ シーケンスにはギャップがある場合があり、順序に従わないこともあります。シーケンスはレプリケートされません。詳細については、「[アクティブ/アクティブレプリケーションでのシーケンスの処理](Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences.md)」を参照してください。
+ DDL とラージオブジェクトはレプリケートされません。
+ セカンダリの一意のインデックスはデータの相違を引き起こす可能性があります。
+ 照合順序はグループ内のすべてのノードで同一である必要があります。
+ ノード間の負荷分散はアンチパターンです。
+ トランザクションが大きいと、レプリケーションの遅延が発生する可能性があります。

# pgactive 拡張機能の初期化
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup"></a>

RDS for PostgreSQL DB インスタンスの `pgactive` 拡張機能を初期化するには、`rds.enable_pgactive` パラメータの値を `1` に設定し、データベースに拡張を作成します。これを行うと、`rds.logical_replication` パラメータと `track_commit_timestamp` パラメータが自動的に有効になり、`wal_level` の値が `logical` に設定されます。

これらのタスクを実行するには、`rds_superuser` ロールとしてアクセス許可が必要です。

AWS マネジメントコンソール または AWS CLI を使用して、必要な RDS for PostgreSQL DB インスタンスを作成できます。以下のステップでは、RDS for PostgreSQL DB インスタンスがカスタム DB パラメータグループに関連付けられていることを前提としています。カスタム DB パラメータグループの作成については、「[Amazon RDS のパラメータグループ](USER_WorkingWithParamGroups.md)」を参照してください。

## コンソール
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.CON"></a>

**pgactive 拡張機能を初期化するには**

1. AWS マネジメントコンソール にサインインし、Amazon RDS コンソール ([https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)) を開きます。

1. ナビゲーションペインで、RDS for PostgreSQL DB インスタンスを選択します。

1. RDS for PostgreSQL DB インスタンスの **[設定]** タブを開きます。インスタンスの詳細で、**[DB インスタンスパラメータグループ]** リンクを見つけます。

1. リンクを選択して、RDS for PostgreSQL DB インスタンスに関連付けられたカスタムパラメータを開きます。

1. `rds.enable_pgactive` パラメータを見つけて `1` に設定し、`pgactive` 機能を初期化します。

1. **[Save changes]** (変更の保存) をクリックします。

1. Amazon RDS コンソールのナビゲーションペインで、**[データベース]** を選択します。

1. RDS for PostgreSQL DB インスタンスを選択し、**[アクション]** メニューから **[再起動]** を選択します。

1. DB インスタンスの再起動を確定して、変更を有効にします。

1. DB インスタンスが使用可能になったら、`psql` または他の任意の PostgreSQL インスタンスを使用して RDS for PostgreSQL DB インスタンスに接続します。

   次の例では、RDS for PostgreSQL DB インスタンスに *postgres* という名前のデフォルトデータベースがあることを前提としています。

   ```
   psql --host=mydb.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password=PASSWORD --dbname=postgres
   ```

1. pgactive が初期化されていることを確認するには、次のコマンドを実行します。

   ```
   postgres=>SELECT setting ~ 'pgactive' 
   FROM pg_catalog.pg_settings
   WHERE name = 'shared_preload_libraries';
   ```

   `pgactive` が `shared_preload_libraries` にある場合、前述のコマンドは以下を返します。

   ```
   ?column? 
   ----------
    t
   ```

## AWS CLI
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.CLI"></a>

**pgactive 拡張機能を初期化するには**

AWS CLI を使用して `pgactive` を設定するには、次の手順に示すように、[modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) オペレーションを呼び出してカスタムパラメータグループ内の特定のパラメータを変更します。

1. AWS CLI コマンドを使用して `rds.enable_pgactive` を `1` に設定し、RDS for PostgreSQL DB インスタンスの `pgactive` 機能を初期化します。

   ```
   postgres=>aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=rds.enable_pgactive,ParameterValue=1,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. 次の AWS CLI コマンドを使用して RDS for PostgreSQL DB インスタンスを再起動し、`pgactive` ライブラリを初期化します。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. インスタンスが使用可能になったら、`psql` を使用して RDS for PostgreSQL DB インスタンスに接続します。

   ```
   psql --host=mydb.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master user --password=PASSWORD --dbname=postgres
   ```

1. pgactive が初期化されていることを確認するには、次のコマンドを実行します。

   ```
   postgres=>SELECT setting ~ 'pgactive' 
   FROM pg_catalog.pg_settings
   WHERE name = 'shared_preload_libraries';
   ```

   `pgactive` が `shared_preload_libraries` にある場合、前述のコマンドは以下を返します。

   ```
   ?column? 
   ----------
    t
   ```

# RDS for PostgreSQL DB インスタンスのアクティブ/アクティブレプリケーションの設定
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.setup-replication"></a>

以下の手順は、`pgactive` が利用可能な場合に 2 つの RDS for PostgreSQL DB インスタンス間でアクティブ/アクティブレプリケーションを開始する方法を示しています。マルチリージョンの高可用性の例を実行するには、2 つの異なるリージョンに Amazon RDS for PostgreSQL インスタンスをデプロイし、VPC ピアリングを設定する必要があります。詳細については、「[VPC ピアリング接続](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html)」を参照してください。

**注記**  
複数のリージョン間でトラフィックを送信すると、追加コストが発生する可能性があります。

次の手順では、RDS for PostgreSQL DB インスタンスが `pgactive` 拡張を使用して有効化されていることを前提としています。詳細については、「[pgactive 拡張機能の初期化](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)」を参照してください。

**`pgactive` 拡張を使用して最初の RDS for PostgreSQL DB インスタンスを設定するには**

次の例は、`pgactive` グループの作成方法と、RDS for PostgreSQL DB インスタンスで `pgactive` 拡張を作成するために必要なその他の手順を示しています。

1. `psql` または別のクライアントツールを使用して、最初の RDS for PostgreSQL DB インスタンスに接続します。

   ```
   psql --host=firstinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password=PASSWORD --dbname=postgres
   ```

1. 次のコマンドを使用して RDS for PostgreSQL インスタンスにデータベースを作成します。

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 次のコマンドを使用して、接続先を新しいデータベースに切り替えます。

   ```
   \c app
   ```

1. 次の SQL ステートメントを使用して、サンプルのテーブルを作成および設定します。

   1. 次の SQL ステートメントを使用してサンプルテーブルを作成します。

      ```
      app=> CREATE SCHEMA inventory;
      CREATE TABLE inventory.products (
      id int PRIMARY KEY, product_name text NOT NULL,
      created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP);
      ```

   1. 次の SQL ステートメントを使用して、サンプルデータをテーブルに入力します。

      ```
      app=> INSERT INTO inventory.products (id, product_name)
      VALUES (1, 'soap'), (2, 'shampoo'), (3, 'conditioner');
      ```

   1. 次の SQL ステートメントを使用して、テーブルにデータが存在することを確認します。

      ```
       app=>SELECT count(*) FROM inventory.products;
      
       count
      -------
       3
      ```

1. 既存のデータベースで `pgactive` 拡張を作成します。

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. pgactive グループを安全に作成して初期化するには、以下のコマンドを使用します。

   ```
   app=>
   -- connection info for endpoint1
   CREATE SERVER pgactive_server_endpoint1
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint1>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint1
       OPTIONS (user 'postgres', password '<password>');
         -- connection info for endpoint2
   CREATE SERVER pgactive_server_endpoint2
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint2>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint2
       OPTIONS (user 'postgres', password '<password>');
   ```

   これで、レプリケーショングループを初期化し、この最初のインスタンスを追加できます。

   ```
   SELECT pgactive.pgactive_create_group(
       node_name := 'endpoint1-app',
       node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1'
   
   );
   ```

   代替手段として、以下のコマンドを使用して pgactive グループを作成および初期化します。ただし、安全性は低くなります。

   ```
   app=> SELECT pgactive.pgactive_create_group(
       node_name := 'node1-app',
       node_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');
   ```

   node1-app は、`pgactive` グループ内のノードを一意に識別するために割り当てる名前です。
**注記**  
パブリックにアクセス可能な DB インスタンスで、このステップを正常に実行するには、`rds.custom_dns_resolution` パラメータを `1` に設定して有効にする必要があります。

1. DB インスタンスの準備が整っているかどうかを確認するには、次のコマンドを使用します。

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready();
   ```

   コマンドが正常に完了した場合は、次の出力が表示されます。

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

**2 番目の RDS for PostgreSQL インスタンスを設定して `pgactive` グループに参加させるには**

次の例は、RDS for PostgreSQL DB インスタンスを `pgactive` グループに参加させる方法と、DB インスタンスに `pgactive` 拡張を作成するために必要なその他のステップを示しています。

次の手順では、RDS for PostgreSQL DB インスタンスが `pgactive` 拡張を使用して設定されていることを前提としています。詳細については、「[pgactive 拡張機能の初期化](Appendix.PostgreSQL.CommonDBATasks.pgactive.basic-setup.md)」を参照してください。

1. `psql` を使用して、パブリッシャーから更新を受け取るインスタンスに接続します。

   ```
   psql --host=secondinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password=PASSWORD --dbname=postgres
   ```

1. 次のコマンドを使用して、2 番目の RDS for PostgreSQL DB インスタンスにデータベースを作成します。

   ```
   postgres=> CREATE DATABASE app;
   ```

1. 次のコマンドを使用して、接続先を新しいデータベースに切り替えます。

   ```
   \c app
   ```

1. 既存のデータベースに `pgactive` 拡張を作成します。

   ```
   app=> CREATE EXTENSION pgactive;
   ```

1. 次に示すように、以下のコマンドを使用して、より安全な方法で RDS for PostgreSQL の 2 番目の DB インスタンスを `pgactive` グループに参加させます。

   ```
   -- connection info for endpoint1
   CREATE SERVER pgactive_server_endpoint1
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint1>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint1
       OPTIONS (user 'postgres', password '<password>');
   
   -- connection info for endpoint2
   CREATE SERVER pgactive_server_endpoint2
       FOREIGN DATA WRAPPER pgactive_fdw
       OPTIONS (host '<endpoint2>', dbname 'app');
   CREATE USER MAPPING FOR postgres
       SERVER pgactive_server_endpoint2
       OPTIONS (user 'postgres', password '<password>');
   ```

   ```
   SELECT pgactive.pgactive_join_group(
       node_name := 'endpoint2-app',
       node_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint2',
       join_using_dsn := 'user_mapping=postgres pgactive_foreign_server=pgactive_server_endpoint1'
   );
   ```

   代替手段として、以下のコマンドを使用して RDS for PostgreSQL の 2 番目の DB インスタンスを `pgactive` グループに参加させます。ただし、安全性は低くなります。

   ```
   app=> SELECT pgactive.pgactive_join_group(
   node_name := 'node2-app',
   node_dsn := 'dbname=app host=secondinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD',
   join_using_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');
   ```

   node2-app は、`pgactive` グループ内のノードを一意に識別するために割り当てる名前です。

1. DB インスタンスの準備が整っているかどうかを確認するには、次のコマンドを使用します。

   ```
   app=> SELECT pgactive.pgactive_wait_for_node_ready(); 
   ```

   コマンドが正常に完了すると、次の出力が表示されます。

   ```
   pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

   最初の RDS for PostgreSQL データベースが比較的大きい場合は、`pgactive.pgactive_wait_for_node_ready()` から復元操作の進行状況レポートを出力されることを確認できます。出力は次の例のようになります:

   ```
   NOTICE:  restoring database 'app', 6% of 7483 MB complete
   NOTICE:  restoring database 'app', 42% of 7483 MB complete
   NOTICE:  restoring database 'app', 77% of 7483 MB complete
   NOTICE:  restoring database 'app', 98% of 7483 MB complete
   NOTICE:  successfully restored database 'app' from node node1-app in 00:04:12.274956
    pgactive_wait_for_node_ready 
   ------------------------------ 
   (1 row)
   ```

   この時点から、`pgactive` は 2 つの DB インスタンス間でデータを同期します。

1. 次のコマンドを使用して、2 番目の DB インスタンスのデータベースにデータがあるかどうかを確認できます。

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   データが正常に同期されると、次の出力が表示されます。

   ```
    count
   -------
    3
   ```

1. 次のコマンドを実行して新しい値を挿入します。

   ```
   app=> INSERT INTO inventory.products (id, product_name) VALUES (4, 'lotion');
   ```

1. 最初の DB インスタンスのデータベースに接続し、次のクエリを実行します。

   ```
   app=> SELECT count(*) FROM inventory.products;
   ```

   アクティブ/アクティブレプリケーションが初期化されると、出力は次のようになります。

   ```
   count
   -------
    4
   ```

**`pgactive` グループから DB インスタンスをデタッチして削除するには**

`pgactive` グループから DB インスタンスをデタッチして削除するには、次の手順に従います。

1. 次のコマンドを使用して、最初のインスタンスから 2 番目の DB インスタンスをデタッチできます。

   ```
   app=> SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']);
   ```

1. 次のコマンドを使用して、2 番目の DB インスタンスから `pgactive` 拡張を削除します。

   ```
   app=> SELECT * FROM pgactive.pgactive_remove();
   ```

   拡張を強制的に削除するには

   ```
   app=> SELECT * FROM pgactive.pgactive_remove(true);
   ```

1. 次のコマンドを使用して拡張をドロップします。

   ```
   app=> DROP EXTENSION pgactive;
   ```

# pgactive メンバー間のレプリケーションラグの測定
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.replicationlag"></a>

次のクエリを使用して、`pgactive` メンバー間のレプリケーションラグを表示できます。全体像を把握するには、すべての `pgactive` ノードでこのクエリを実行します。

```
    
app=> SELECT * FROM pgactive.pgactive_get_replication_lag_info();
│-[ RECORD 1 ]--------+---------------------------------------------
│node_name            | node2-app
│node_sysid           | 7481018224801653637
│application_name     | pgactive:7481018224801653637:send
│slot_name            | pgactive_16385_7481018224801653637_0_16385__
│active               | t
│active_pid           | 783486
│pending_wal_decoding | 0
│pending_wal_to_apply | 0
│restart_lsn          | 0/2108150
│confirmed_flush_lsn  | 0/2154690
│sent_lsn             | 0/2154690
│write_lsn            | 0/2154690
│flush_lsn            | 0/2154690
│replay_lsn           | 0/2154690
│-[ RECORD 2 ]--------+---------------------------------------------
│node_name            | node1-app
│node_sysid           | 7481018033434600853
│application_name     | pgactive:7481018033434600853:send
│slot_name            | pgactive_16385_7481018033434600853_0_16385__
│active               | t
│active_pid           | 783488
│pending_wal_decoding | 0
│pending_wal_to_apply | 0
│restart_lsn          | 0/20F5AD0
│confirmed_flush_lsn  | 0/214EF68
│sent_lsn             | 0/214EF68
│write_lsn            | 0/214EF68
│flush_lsn            | 0/214EF68
│replay_lsn           | 0/214EF68
```

少なくとも次の診断をモニタリングします。

アクティブ  
アクティブが false の場合にアラートを設定します。これは、スロットが現在使用されていない (サブスクライバーインスタンスがパブリッシャーから切断された) ことを示します。

Pending\$1wal\$1decoding  
PostgreSQL の論理レプリケーションでは、WAL ファイルはバイナリ形式で保存されます。パブリッシャーは、これらの WAL の変更をデコードし、論理的な変更 (挿入、更新、削除オペレーションなど) に変換する必要があります。  
pending\$1wal\$1decoding メトリクスは、パブリッシャー側でデコードを待っている WAL ファイルの数を示します。  
この数は、次の要因により増加する可能性があります。  
+ サブスクライバーが接続されていない場合、アクティブステータスは false になり、pending\$1wal\$1decoding は増加する
+ スロットはアクティブだが、パブリッシャーは WAL の変更の量に対応できない

pending\$1wal\$1to\$1apply  
pending\$1wal\$1apply メトリクスは、サブスクライバー側で適用を待っている WAL ファイルの数を示します。  
いくつかの要因により、サブスクライバーが変更を適用できなくなり、ディスクがいっぱいになるシナリオが発生する可能性があります。  
+ スキーマの違い - サンプルという名前のテーブルの WAL ストリームに変更があっても、そのテーブルがサブスクライバー側に存在しない場合など
+ プライマリキー列の値が更新された場合
+ セカンダリの一意のインデックスはデータの相違を引き起こす可能性がある

# pgactive 拡張機能のパラメータ設定
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters"></a>

次のクエリを使用すると、`pgactive` 拡張に関連するすべてのパラメータを表示できます。

```
app=> SELECT * FROM pg_settings WHERE name LIKE 'pgactive.%';
```

`pgactive` 拡張機能は、さまざまなパラメータを使用して設定できます。これらのパラメータは、AWS マネジメントコンソール または CLI AWS インターフェイスから設定できます。

## 主な pgactive 拡張機能パラメータ
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.mainparams"></a>

次の表は、`pgactive` 拡張機能の主なパラメータのリファレンスです。


| パラメータ | 単位 | デフォルト | 説明  | 
| --- | --- | --- | --- | 
| pgactive.conflict\$1logging\$1include\$1tuples | `boolean` | –  | `pgactive` 拡張機能の完全なタプル情報をログに記録します。  変更を有効にするには、サーバーの再起動が必要です。  | 
| pgactive.log\$1conflicts\$1to\$1table | `boolean` | –  | `pgactive` 拡張機能が検出された競合を `pgactive.pgactive_conflict_history` テーブルにログ記録するかどうかを決定します。詳細については、「競合のログ記録」を参照してください。  変更を有効にするには、サーバーの再起動が必要です。  | 
| pgactive.log\$1conflicts\$1to\$1logfile | `boolean` | –  | `pgactive` 拡張機能が検出された競合を PostgreSQL ログファイルに記録するかどうかを決定します。詳細については、「競合のログ記録」を参照してください。  変更を有効にするには、サーバーの再起動が必要です。  | 
| pgactive.synchronous\$1commit | `boolean` | 化 | pgactive 適用ワーカーのコミット動作を決定します。無効 (オフ) にすると、適用ワーカーは非同期コミットを実行します。これにより、適用オペレーション中の PostgreSQL のスループットが向上しますが、アップストリームへのリプレイ確認が遅延します。`off` に設定しても常に安全であり、トランザクションの損失やスキップは発生しません。この設定は、ダウンストリームノードでのディスクフラッシュのタイミングと、確認がアップストリームに送信されるタイミングにのみ影響します。システムは、チェックポイントや定期的な作業などの関連しないオペレーションを通じてコミットがディスクにフラッシュされるまで、リプレイフラッシュ確認の送信を遅らせます。ただし、アップストリームノードの `synchronous_standby_names` にダウンストリームがリストされている場合、`off` に設定すると、アップストリームノードでの同期コミットがクライアントに成功を報告するまでの時間が長くなります。この場合、パラメータは `on` に設定してください。  このパラメータが `on` に設定されていても、`synchronous_standby_names` にノードがリストされている場合は、アクティブ/アクティブ設定ではレプリケーションの競合が発生する可能性があります。これは、システムにはノード間ロックとグローバルスナップショット管理がないため、異なるノード上の同時トランザクションが同じタプルを変更できるためです。さらに、トランザクションはアップストリームノードでコミットした後にのみレプリケーションを開始します。同期コミットを有効にしても、pgactive 拡張機能が常時一貫性のあるシステムになるわけではありません。  | 
| pgactive.temp\$1dump\$1directory | `string` | – | 初期設定時のデータベースクローン作成オペレーションに必要な一時ストレージパスを定義します。このディレクトリは postgres ユーザーによって書き込み可能で、完全なデータベースダンプを格納するのに十分なストレージ容量を持っている必要があります。システムは、論理コピーオペレーションによるデータベースの初期セットアップ中にのみ、この場所を使用します。このパラメータは、`pgactive_init_copy command` では使用されません。 | 
| pgactive.max\$1ddl\$1lock\$1delay | `milliseconds` | `-1` | 同時書き込みトランザクションを強制的に中止するまでの DDL ロックの最大待機時間を指定します。デフォルト値は `-1` で、`max_standby_streaming_delay` で設定された値が使用されます。このパラメータには時間単位を指定できます。例えば、10 秒の場合は 10s と設定できます。この待機期間中、システムは進行中の書き込みトランザクションがコミットまたはロールバックされるのを待つ間に DDL ロックの取得を試みます。詳細については、「DDL ロック」を参照してください。 | 
| pgactive.ddl\$1lock\$1timeout | `milliseconds` | `-1` | DDL ロック試行がロックの取得を待機する時間を指定します。デフォルト値は `-1` で、lock\$1timeout で指定された値を使用します。このパラメータは、10 秒の場合は 10s などの時間単位で設定できます。このタイマーは、DDL ロックを取得するための待機期間のみを制御します。システムがロックを取得し、DDL オペレーションを開始すると、タイマーは停止します。このパラメータは、DDL ロックを保持できる合計期間や全体的な DDL オペレーション時間を制限するものではありません。オペレーションの合計期間を制御するには、代わりに `statement_timeout` を使用します。詳細については、「DDL ロック」を参照してください。 | 
| pgactive.debug\$1trace\$1ddl\$1locks\$1level | `boolean` | –  | `pgactive` 拡張機能の DDL ロックオペレーションのデフォルトのデバッグログレベルを上書きします。この設定を行うと、DDL ロック関連のメッセージがデフォルトレベルではなく LOG デバッグレベルで出力されます。このパラメータを使用して、サーバー全体で詳細な `DEBUG1` または `DEBUG2` ログレベルを有効にせずに、DDL ロックアクティビティをモニタリングできます。 詳細度の高い順序で使用可能なログレベル。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) モニタリングオプションの詳細については、「グローバル DDL ロックのモニタリング」を参照してください。  この設定の変更は、設定を再読み込みすると有効になります。サーバーを再起動する必要はありません。   | 

## 追加の pgactive 拡張機能パラメータ
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.addparams"></a>

次の表は、`pgactive` 拡張機能で利用可能な、あまり使用されない内部設定オプションを示しています。


| パラメータ | 単位 | デフォルト | 説明  | 
| --- | --- | --- | --- | 
| pgactive.debug\$1apply\$1delay | `integer` | – |  `pgactive.pgactive_connections` エントリに明示的に適用遅延が指定されていない設定済み接続の適用遅延 (ミリ秒単位) を設定します。この遅延はノード作成時または参加時に設定され、pgactive はコミットされてから指定されたミリ秒数が経過するまで、ピアノードでトランザクションをリプレイしません。 主に、テスト環境で高レイテンシーのネットワークをシミュレートして、競合を簡単に作成するために使用します。例えば、ノード A とノード B に 500 ミリ秒の遅延が設定されている場合、ノード A に値を挿入した後、ノード B で競合する挿入を実行するために少なくとも 500 ミリ秒の猶予があります。  適用ワーカーを有効にするには、サーバーの再ロードまたは再起動が必要です。  | 
| pgactive.connectability\$1check\$1duration | `integer` | –  | データベースワーカーが接続の確立に失敗した場合に、接続を確立しようとする時間 (秒単位) を指定します。ワーカーは、成功するかこのタイムアウト値に達するまで、1 秒ごとに接続を試行します。この設定は、ワーカーが接続を確立する準備ができる前にデータベースエンジンが起動する場合に便利です。 | 
| pgactive.skip\$1ddl\$1replication | `boolean` | `on` | `pgactive` が有効になっている Amazon RDS で DDL の変更をレプリケートまたは処理する方法を制御します。`on` に設定すると、ノードは非 pgcctive ノードと同様に DDL 変更を処理します。このパラメータを使用する場合、以下の要件が適用されます。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) このパラメータは、スーパーユーザー権限を使用してグローバル、ローカル (セッションレベル) の 2 つの方法で変更できます。  このパラメータを誤って変更すると、レプリケーションのセットアップが中断される可能性があります。  | 
| pgactive.do\$1not\$1replicate | `boolean` | – | このパラメータは内部使用のみを目的としています。トランザクションでこのパラメータを設定すると、変更は DB クラスター内の他のノードにレプリケートされません。  このパラメータを誤って変更すると、レプリケーションのセットアップが中断される可能性があります。  | 
| pgactive.discard\$1mismatched\$1row\$1attributes | `boolean` | –  | このパラメータは専門家による使用のみを目的としています。このパラメータは、特定のレプリケーションの問題をトラブルシューティングする場合にのみ使用することをお勧めします。このパラメータは、次の場合に使用します。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) この設定により、以下のエラーメッセージがオーバーライドされ、データの不一致が発生してもレプリケーションは続行されます。「`cannot right-pad mismatched attributes; attno %u is missing in local table and remote row has non-null, non-dropped value for this attribute`」  このパラメータを誤って変更すると、レプリケーションのセットアップが中断される可能性があります。   | 
| pgactive.debug\$1trace\$1replay | `boolean` | – | `on` に設定すると、ダウンストリームの適用ワーカーが処理するリモートアクションごとにログメッセージが出力されます。ログには以下が含まれます。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) ログには、キューに登録された DDL コマンドとテーブルの DROP も記録されます。para> デフォルトでは、ログには行フィールドの内容は含まれません。ログに行の値を含めるには、次のフラグを有効にして再コンパイルする必要があります。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html)  このログ記録設定を有効にすると、パフォーマンスに影響する可能性があります。トラブルシューティングに必要な場合にのみ有効にすることをお勧めします。この設定の変更は、設定を再読み込みすると有効になります。サーバーを再起動する必要はありません。   | 
| pgactive.extra\$1apply\$1connection\$1options |  | – | pgactive ノードとのすべてのピアノード接続の接続パラメータを設定できます。これらのパラメータは、keepalives や SSL モードなどの設定を制御します。デフォルトでは、pgactive は次の接続パラメータを使用します。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) デフォルトのパラメータを上書きするには、以下の同様のコマンドを使用します。 pgactive.extra\$1apply\$1connection\$1options = 'keepalives=0' 個々のノード接続文字列は、これらの設定と pgactive の組み込み接続オプションの両方よりも優先されます。接続文字列形式の詳細については、「[libpq connection strings](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING)」を参照してください。 デフォルトの keepalives 設定は有効のままにすることをお勧めします。信頼性の低いネットワーク経由で大規模なトランザクションが完了する際に問題が発生する場合にのみ、keepalives を無効にしてください。  デフォルトのkeepalives 設定は有効のままにすることをお勧めします。信頼性の低いネットワーク経由で大規模なトランザクションが完了する際に問題が発生する場合にのみ、keepalives を無効にしてください。この設定の変更は、設定を再読み込みすると有効になります。サーバーを再起動する必要はありません。  | 
| pgactive.init\$1node\$1parallel\$1jobs (int) |  | – | `pgactive.pgactive_join_group` 関数を使用して、論理ノードの結合時に `pg_dump` と `pg_restore` が使用できる並列ジョブの数を指定します。 この設定の変更は、設定を再読み込みすると有効になります。サーバーを再起動する必要はありません。 | 
| pgactive.max\$1nodes | `int` | 4 |  pgactive 拡張グループで許可されるノードの最大数を指定します。デフォルト値は 4 ノードです。このパラメータの値を設定するときは、次の点を考慮する必要があります。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.pgactive.parameters.html) このパラメータは、設定ファイルで設定する方法と、`ALTER SYSTEM SET` コマンドを使用する方法の 2 つの方法で設定できます。 このパラメータのデフォルト値は `4` です。つまり、`pgactive` 拡張グループには、いつでも最大 4 ノードまでしか参加できません。  この変更は、サーバーを再起動した後に有効になります。  | 
| pgactive.permit\$1node\$1identifier\$1getter\$1function\$1creation | `boolean` | – | このパラメータは、内部使用のみを目的としています。有効にすると、`pgactive` 拡張機能により、pgactive ノード識別子 getter 関数の作成が可能になります。 | 

# アクティブ/アクティブ競合について
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.replication"></a>

pgactive をアクティブ/アクティブモードで使用する場合、複数のノードから同じテーブルに書き込むと、データの競合が発生する可能性があります。一部のクラスタリングシステムでは、同時アクセスを防ぐために分散ロックを使用していますが、pgactive は地理的に分散されたアプリケーションに適した楽観的なアプローチを採用しています。

一部のデータベースクラスタリングシステムは、分散ロックを使用して同時データアクセスを防止します。このアプローチはサーバーが近接している場合に機能しますが、優れたパフォーマンスのためには非常に低いレイテンシーが必要となるため、地理的に分散したアプリケーションはサポートしていません。pgactive 拡張機能は、分散ロック (悲観的アプローチ) を使用する代わりに、楽観的アプローチを使用します。つまり、次のことを意味します。
+ 可能な場合には競合を回避できます。
+ 特定のタイプの競合の発生を許可します。
+ 競合が発生した場合に競合を解決します。

このアプローチにより、分散アプリケーションを構築する際の柔軟性が向上します。

## 競合の発生方法
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.howconflicts"></a>

ノード間の競合は、関連するすべてのトランザクションが同じノードで同時に発生した場合には発生しない一連のイベントから発生します。ノード間の変更はトランザクションのコミット後にのみ行われるため、各トランザクションはコミットされたノードで個別に有効ですが、その間に他の作業を行った別のノードで実行された場合は有効になりません。pgactive 適用は基本的に他のノードでトランザクションを再実行するため、適用されているトランザクションと受信側ノードでコミットされたトランザクションの間に競合がある場合、再実行オペレーションが失敗する可能性があります。

 すべてのトランザクションが単一のノードで実行されている場合にほとんどの競合が発生しないのは、PostgreSQL にそれを防ぐためのトランザクション間通信メカニズムがあるからです。これには、以下が含まれます。
+ UNIQUE インデックス
+ SEQUENCE
+ 行とリレーションのロック
+ SERIALIZABLE 依存関係の追跡

これらのメカニズムはすべて、望ましくない同時実行の問題を防ぐためにトランザクション間で通信する方法です。

pgactive は、分散トランザクションマネージャーやロックマネージャーを使用しないため、低レイテンシーを実現し、ネットワークパーティションを適切に処理します。ただし、これは、異なるノード上のトランザクションが相互に完全に分離して実行されることを意味します。通常、分離はデータベースの一貫性を向上させますが、この場合は、競合を防ぐために分離を減らす必要があります。

## 競合のタイプ
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflicttypes"></a>

発生する可能性のある競合には、以下が含まれます。

**Topics**
+ [PRIMARY KEY または UNIQUE の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict1)
+ [INSERT/INSERT の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict2)
+ [複数の UNIQUE 制約に違反する INSERT](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict3)
+ [UPDATE/UPDATE の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict4)
+ [PRIMARY KEY の UPDATE 競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict5)
+ [複数の UNIQUE 制約に違反するUPDATE](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict6)
+ [UPDATE/DELETE の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict7)
+ [INSERT/UPDATE の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict8)
+ [DELETE/DELETE の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict9)
+ [外部キー制約の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict10)
+ [排他制約の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict11)
+ [グローバルデータの競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict12)
+ [ロックの競合とデッドロックの中止](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict13)
+ [相違による競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14)

### PRIMARY KEY または UNIQUE の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict1"></a>

行の競合は、複数のオペレーションが単一のノードで同じ行キーを変更しようとしたときに発生します。これらの競合は、最も一般的なタイプのデータ競合です。

pgactive は検出された競合を、最終更新を優先する処理またはカスタム競合ハンドラーで解決します。

行の競合には以下が含まれます。
+ INSERT と INSERT
+ INSERT と UPDATE
+ UPDATE と DELETE
+ INSERT と DELETE
+ DELETE と DELETE
+ INSERT と DELETE

### INSERT/INSERT の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict2"></a>

この最も一般的な競合は、2 つの異なるノードの INSERT が同じ PRIMARY KEY 値 (または PRIMARY KEY が存在しない場合は同じ UNIQUE 制約値) を持つタプルを作成するときに発生します。

pgactivelink は、発信元ホストのタイムスタンプを使用して最新のタプルを保持することで、INSERT の競合を解決します。このデフォルトの動作は、カスタム競合ハンドラーで上書きできます。このプロセスでは特別な管理者アクションは必要ありませんが、pgactivelink はノード全体で 1 つの INSERT オペレーションを破棄することに注意してください。カスタムハンドラーが実装しない限り、自動データマージは発生しません。

pgactivelink は、単一の制約違反に関連する競合のみを解決できます。INSERT が複数の UNIQUE 制約に違反している場合は、追加の競合解決戦略を実装する必要があります。

### 複数の UNIQUE 制約に違反する INSERT
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict3"></a>

INSERT/INSERT 競合は、PRIMARY KEY を含む複数の UNIQUE 制約に違反する可能性があります。pgactivelink は、単一の UNIQUE 制約を含む競合のみを処理できます。競合が複数の UNIQUE 制約に違反すると、適用ワーカーは失敗し、次のエラーを返します。

`multiple unique constraints violated by remotely INSERTed tuple.`

古いバージョンでは、この状況では代わりに「一意性の相違による競合」エラーが発生しました。

これらの競合を解決するには、手動でアクションを実行する必要があります。競合するローカルタプルを DELETE するか、UPDATE して新しいリモートタプルとの競合を削除します。複数の競合するタプルに対処する必要がある場合があることに注意してください。現在、pgactivelink には、複数の一意の制約に違反するタプルを無視、破棄、またはマージする組み込み機能はありません。

**注記**  
詳細については、「複数の UNIQUE 制約に違反する UPDATE」を参照してください。

### UPDATE/UPDATE の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict4"></a>

この競合は、2 つのノードが PRIMARY KEY を変更せずに同じタプルを同時に変更した場合に発生します。pgactivelink は、定義されている場合には、最終更新を優先するロジックまたはカスタム競合ハンドラーを使用してこれらの競合を解決します。PRIMARY KEY は、タプルマッチングと競合の解決に不可欠です。PRIMARY KEY のないテーブルの場合、pgactivelink は次のエラーで UPDATE オペレーションを拒否します。

`Cannot run UPDATE or DELETE on table (tablename) because it does not have a primary key.`

### PRIMARY KEY の UPDATE 競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict5"></a>

pgactive は、PRIMARY KEY 更新を処理する際に制限があります。PRIMARY KEY で UPDATE オペレーションを実行することはできますが、pgactive はこれらのオペレーションに最終更新を優先するロジックを使用して競合を自動的に解決することはできません。PRIMARY KEY の更新が既存の値と競合しないようにする必要があります。PRIMARY KEY の更新中に競合が発生した場合、相違による競合が発生し、手動による介入が必要になります。これらの状況の処理の詳細については、「[相違による競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14)」を参照してください。

### 複数の UNIQUE 制約に違反するUPDATE
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict6"></a>

pgactivelink は、受信する UPDATE が複数の UNIQUE 制約または PRIMARY KEY 値に違反している場合、最終更新を優先する競合解決を適用できません。この動作は、複数の制約違反がある INSERT オペレーションに似ています。このような状況では、手動による介入を必要とする相違による競合が発生します。詳細については、「[相違による競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14)」を参照してください。

### UPDATE/DELETE の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict7"></a>

この競合は、あるノードが行を UPDATE し、別のノードが同時にその行を DELETE した場合に発生します。この場合、再実行時に UPDATE/DELETE 競合が発生します。解決策は、カスタム競合ハンドラーが特に指定しない限り、DELETE の後に送信される UPDATE をすべて破棄することです。

pgactivelink は、タプルを照合して競合を解決するために PRIMARY KEY を必要とします。PRIMARY KEY のないテーブルの場合、次のエラーで DELETE オペレーションが拒否されます。

`Cannot run UPDATE or DELETE on table (tablename) because it does not have a primary key.`

**注記**  
pgactivelink は、UPDATE/DELETE と INSERT/UPDATE の競合を区別できません。どちらの場合も、UPDATE は存在しない行に影響します。非同期レプリケーションおよびノード間に再実行順序がないことにより、pgactivelink は UPDATE が新しい行 (INSERT をまだ受信していない) に対するものか、削除された行に対するものかを判断できません。どちらのシナリオでも、pgactivelink は UPDATE を破棄します。

### INSERT/UPDATE の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict8"></a>

この競合は、マルチノード環境で発生する可能性があります。これは、あるノードが行を INSERT し、2 番目のノードが行を UPDATE し、3 番目のノードが元の INSERT の前に UPDATE を受信したときに発生します。デフォルトでは、カスタム競合トリガーで特に指定されていない限り、pgactivelink は UPDATE を破棄することで、これらの競合を解決します。この解決方法により、ノード間でデータの不整合が発生する可能性があることに注意してください。同様のシナリオとその処理の詳細については、「[UPDATE/DELETE の競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict7)」を参照してください。

### DELETE/DELETE の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict9"></a>

この競合は、2 つの異なるノードが同じタプルを同時に削除した場合に発生します。pgactivelink は、両方の DELETE オペレーションの結果が同じであるため、これらの競合を無害と見なします。このシナリオでは、pgactivelink はデータ整合性に影響を与えることなく、一方の DELETE オペレーションを安全に無視します。

### 外部キー制約の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict10"></a>

FOREIGN KEY の制約により、既存のローカルデータにリモートトランザクションを適用するときに競合が発生する可能性があります。これらの競合は通常、トランザクションが発信元ノードの論理順序とは異なる順序で適用された場合に発生します。

デフォルトでは、pgactive は session\$1replication\$1role を `replica` として変更を適用し、レプリケーション中に外部キーチェックをバイパスします。アクティブ/アクティブ設定では、これが外部キー違反につながる可能性があります。ほとんどの違反は一時的なものであり、レプリケーションが追いつくと解決されます。ただし、pgactive はクロスノードの行ロックをサポートしていないため、外部キーのダングリングが発生する可能性があります。

この動作は、分断耐性のある非同期アクティブ/アクティブシステムに固有のものです。例えば、ノード A が新しい子行を挿入すると同時に、ノード B がその親行を削除する場合があります。システムは、ノード間でのこのタイプの同時変更を防ぐことはできません。

外部キーの競合を最小限に抑えるには、以下のことをお勧めします。
+ 外部キー関係を密接に関連するエンティティに制限します。
+ 可能な場合は、単一のノードから関連エンティティを変更します。
+ ほとんど変更を必要としないエンティティを選択します。
+ 変更に対してアプリケーションレベルの同時実行制御を実装します。

### 排他制約の競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict11"></a>

 pgactivelink は排他制約をサポートしておらず、作成を制限します。

**注記**  
既存のスタンドアロンデータベースを pgactivelink データベースに変換する場合は、すべての排他制約を手動で削除します。

分散非同期システムでは、制約に違反する行のセットが存在しないことは保証できません。これは、異なるノード上のすべてのトランザクションが完全に分離されているためです。排他制約は、排他制約違反のためにどのノードからも別のノードに再実行できなくなる、再実行デッドロックにつながる可能性があります。

pgactivelink に排他制約の作成を強制した場合、またはスタンドアロンデータベースを pgactivelink に変換するときに既存の排他制約を削除しない場合、レプリケーションが中断する可能性があります。レプリケーションの進行状況を回復するには、受信リモートタプルと競合するローカルタプルを削除または変更し、リモートトランザクションを適用できるようにします。

### グローバルデータの競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict12"></a>

pgactivelink を使用する場合、ノード間でロールなどの PostgreSQL システム全体のグローバルデータが異なると、競合が発生する可能性があります。これらの競合により、オペレーション (主に DDL) が 1 つのノードで成功してコミットされるものの、他のノードには適用されない可能性があります。

ユーザーが 1 つのノードに存在するものの、別のノードには存在しない場合、レプリケーションの問題が発生する可能性があります。
+ Node1 には `fred` という名前のユーザーがいますが、このユーザーは Node2 には存在しません。
+ `fred` が Node1 にテーブルを作成すると、テーブルは `fred` を所有者としてレプリケートされます。
+ この DDL コマンドを Node2 に適用すると、ユーザー `fred` が存在しないため、失敗します。
+ この失敗により、Node2 の PostgreSQL ログに ERROR が生成され、`pgactive.pgactive_stats.nr_rollbacks` カウンターが増分されます。

**解決策:** Node2 でユーザー `fred` を作成します。ユーザーが同じアクセス許可を持つ必要はありませんが、両方のノードに存在する必要があります。

1 つのノードにテーブルが存在するものの、別のノードには存在しない場合、データ変更オペレーションは失敗します。
+ Node1 には、Node2 に存在しない `foo` という名前のテーブルがあります。
+ Node1 の `foo` テーブルに対する DML オペレーションは、Node2 にレプリケートされると失敗します。

**解決策:** 同じ構造で Node2 にテーブル `foo` を作成します。

**注記**  
pgactivelink は現在、CREATE USER コマンドまたは DDL オペレーションをレプリケートしません。DDL レプリケーションは将来のリリースが予定されています。

### ロックの競合とデッドロックの中止
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict13"></a>

pgactive 適用プロセスは通常のユーザーセッションのように動作するため、標準的な行とテーブルのロックルールに従います。そのため、pgactivelink 適用プロセスは、ユーザートランザクションまたは他の適用プロセスによって保持されているロックを待機する可能性があります。

以下のタイプのロックは適用プロセスに影響を与える可能性があります。
+ ユーザーセッションによる明示的なテーブルレベルのロック (LOCK TABLE...)
+ ユーザーセッションによる明示的な行レベルのロック (SELECT ... FOR UPDATE/FOR SHARE)
+ 外部キーからのロック
+ ローカルアクティビティまたは他のサーバーからの行の UPDATE、INSERT、または DELETE による暗黙的なロック

デッドロックは、次の間で発生する可能性があります。
+ pgactivelink 適用プロセスとユーザートランザクション
+ 2 つの適用プロセス

デッドロックが発生すると、PostgreSQL のデッドロック検出機能は問題のトランザクションのうち 1 つを終了します。pgactivelink 適用ワーカーのプロセスが終了すると、自動的に再試行され、通常は成功します。

**注記**  
これらの問題は一時的なものであり、通常は管理者の介入は必要ありません。適用プロセスがアイドル状態のユーザーセッションのロックによって長期間ブロックされている場合は、ユーザーセッションを終了してレプリケーションを再開できます。この状況は、ユーザーが別のユーザーセッションに影響を与える長期間にわたるロックを保持する場合に似ています。
ロック関連の再生遅延を特定するには、PostgreSQL で `log_lock_waits` 機能を有効にします。

### 相違による競合
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict14"></a>

ノード間で同一であるはずのデータが予期せず異なる場合、相違による競合が発生します。これらの競合は発生すべきではないものの、現在の実装ではすべてを確実に防止できるわけではありません。

**注記**  
 行の PRIMARY KEY を変更すると、すべてのノードが変更を処理する前に別のノードが同じ行のキーを変更した場合、相違による競合が発生する可能性があります。プライマリキーの変更を避けるか、変更を指定された 1 つのノードに制限してください。詳細については、「[PRIMARY KEY の UPDATE 競合](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflict5)」を参照してください。

行データが関係した相違による競合には通常、管理者の介入が必要です。これらの競合を解決するには、`pgactive.pgactive_do_not_replicate` を使用してレプリケーションを一時的に無効にし、一方のノードのデータをもう一方のノードに合わせて手動で調整する必要があります。これらの競合は、pgactive を記載通りに使用し、安全でないとマークされた設定や関数を回避すれば、発生しません。

 管理者は、これらの競合を手動で解決する必要があります。競合タイプによっては、`pgactive.pgactive_do_not_replicate` などの高度なオプションを使用する必要があります。不適切に使用すると状況が悪化する可能性があるため、これらのオプションは慎重に使用してください。競合にはさまざまな可能性が考えられるため、普遍的な解決の手順を提供することはできません。

異なるノード間で同一であるはずのデータが予期せず異なる場合、相違による競合が発生します。これらの競合は発生すべきではないものの、現在の実装ではこのような競合をすべて確実に防止できるわけではありません。

## 競合の回避または許容
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.avoidconflicts"></a>

 ほとんどの場合、適切なアプリケーション設計を使用することで、競合を回避したり、アプリケーションが競合を許容するようにしたりできます。

 競合は、複数のノードで同時操作が行われた場合にのみ発生します。競合を回避するには、以下を行います。
+ 1 つのノードにのみ書き込む
+ 各ノードの独立したデータベースサブセットに書き込む (各ノードに個別のスキーマを割り当てるなど)

INSERT と INSERT の競合の場合は、グローバルシーケンスを使用して競合を完全に防止します。

 競合が許容できないユースケースの場合は、アプリケーションレベルで分散ロックを実装することを検討してください。多くの場合、最善の方法は、すべての競合を防ぐのではなく、pgactive の競合解決メカニズムと連携するようにアプリケーションを設計することです。詳細については、「[競合のタイプ](#Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflicttypes)」を参照してください。

## 競合のログ記録
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.actact.conflictlogging"></a>

pgactivelink は、競合インシデントを `pgactive.pgactive_conflict_history` テーブルに記録し、アクティブ/アクティブ競合の診断と処理に役立つようにします。このテーブルへの競合ログは、`pgactive.log_conflicts_to_table` を true に設定した場合にのみ記録されます。pgactive 拡張機能は、log\$1min\$1messages が `LOG` または `lower` に設定されている場合に、`pgactive.log_conflicts_to_table` 設定に関係なく、競合を PostgreSQL ログファイルにも記録します。

 競合履歴テーブルは、以下の目的で使用します。
+ アプリケーションに競合が起きる頻度を測定する
+ 競合が発生する場所を特定する
+ アプリケーションを改善し、競合率を低減する
+ 競合の解決策により望ましい結果が得られないケースを検出する
+ ユーザー定義の競合トリガーまたはアプリケーション設計の変更が必要な場所を特定する

 行が競合した場合、オプションで行の値をログに記録できます。これは `pgactive.log_conflicts_to_table` 設定によって制御されます。以下の点に注意してください。
+ これはデータベース全体のグローバルオプションです。
+ 行値のログ記録をテーブル別に制御することはできません。
+ フィールド番号、配列要素、またはフィールド長に制限はありません。
+ 競合を引き起こす可能性のある数メガバイトの行を使用する場合は、この機能を有効にすることはお勧めできません。

 競合履歴テーブルには、データベース内のすべてのテーブルのデータ (それぞれ異なるスキーマを持つ可能性がある) が含まれているため、ログに記録された行値は JSON フィールドとして保存されます。JSON は、SQL から直接呼び出す場合と同様に、`row_to_json` を使用して作成されます。PostgreSQL では `json_to_row` 関数が提供されていないため、ログに記録された JSON から複合型のタプルを再構築するには、テーブル固有のコード (PL/pgSQL、PL/Python、PL/Perl など) が必要です。

**注記**  
ユーザー定義の競合のサポートは、今後の拡張機能として計画されています。

# pgactive スキーマについて
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.schema"></a>

pgactive スキーマは、RDS for PostgreSQL のアクティブ/アクティブレプリケーションを管理します。このスキーマには、レプリケーション設定とステータス情報を保存するテーブルが含まれています。

**注記**  
pgactive スキーマは進化しており、変更される可能性があります。これらのテーブルのデータを直接変更しないでください。

pgactive スキーマのキーテーブルには以下のものが含まれます。
+ `pgactive_nodes` − アクティブ/アクティブレプリケーショングループ内のノードに関する情報を保存します。
+ `pgactive_connections` − 各ノードの接続の詳細を保存します。

## pgactive\$1nodes
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.schema.nodes"></a>

pgactive\$1nodes は、アクティブ/アクティブレプリケーショングループに参加しているノードに関する情報を保存します。


| 列 | タイプ | 照合 | Nullable | デフォルト | 
| --- | --- | --- | --- | --- | 
| node\$1sysid | text | – | NOT NULL | – | 
| node\$1timeline | oid | – | NOT NULL | – | 
| node\$1dboid | oid | – | NOT NULL | – | 
| node\$1status | char | – | NOT NULL | – | 
| node\$1name | text | – | NOT NULL | – | 
| node\$1dsn | text | – | NOT NULL | – | 
| node\$1init\$1from\$1dsn | text | – | NOT NULL | – | 
| node\$1read\$1only | ブール値 | – | – | false | 
| node\$1seq\$1id | smallint | – | NOT NULL | – | 

**node\$1sysid**  
ノードの一意の ID。`pgactive_create_group` または `pgactive_join_group` 中に生成されます。

**node\$1status**  
ノードの準備状況:  
+ **b** - セットアップの開始
+ **i** - 初期化
+ **c** - キャッチアップ
+ **o** - アウトバウンドスロットの作成
+ **r** - 準備完了
+ **k** - 強制終了
この列は、ノードが接続されているか切断されているかを示しません。

**node\$1name**  
ユーザーが指定した一意のノード名。

**node\$1dsn**  
接続文字列またはユーザーマッピング名

**node\$1init\$1from\$1dsn**  
このノードが作成された DSN。

## pgactive\$1connection
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.schema.connection"></a>

pgactive\$1connections は、各ノードの接続の詳細を保存します。


| 列 | タイプ | 照合 | Nullable | デフォルト | 
| --- | --- | --- | --- | --- | 
| conn\$1sysid | text | なし | NOT NULL | なし | 
| conn\$1timeline | oid | なし | NOT NULL | なし | 
| conn\$1dboid | oid | なし | NOT NULL | なし | 
| conn\$1dsn | text | なし | NOT NULL | なし | 
| conn\$1apply\$1delay | integer | なし | なし | なし | 
| conn\$1replication\$1sets | text | なし | なし | なし | 

conn\$1sysid  
このエントリが参照するノードのノード識別子。

conn\$1dsn  
pgactive.pgactive\$1nodes `node_dsn` と同じです。

conn\$1apply\$1delay  
設定されている場合、リモートノードから各トランザクションを適用するまで待機するミリ秒数。主にデバッグ用。null の場合、グローバルデフォルトが適用されます。

## レプリケーションセットの使用
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.replication"></a>

レプリケーションセットは、レプリケーションオペレーションに含めるテーブルと除外するテーブルを決定します。デフォルトでは、次の関数を使用して指定しない限り、すべてのテーブルがレプリケートされます。
+ `pgactive_exclude_table_replication_set()` - 指定されたテーブルをレプリケーションから除外する
+ `pgactive_include_table_replication_set()` - 指定されたテーブルをレプリケーションに含める

**注記**  
レプリケーションセットを設定する前に、次の点を考慮してください。  
テーブルの包含または除外は、`pgactive_create_group()` の実行後、`pgactive_join_group()` を実行するより前にのみ設定できます。
`pgactive_exclude_table_replication_set()` を使用した後、`pgactive_include_table_replication_set()` を使用することはできません。
`pgactive_exclude_table_replication_set()` を使用した後、`pgactive_include_table_replication_set()` を使用することはできません。

システムは、初期設定に基づいて新しく作成されたテーブルを異なる方法で処理します。
+ テーブルを除外した場合: `pgactive_join_group()` 以降に作成された新しいテーブルは、自動的にレプリケーションに含まれます。
+ テーブルを含めた場合: `pgactive_join_group()` 以降に作成された新しいテーブルは、自動的にレプリケーションから除外されます。

特定のテーブルのレプリケーションセット設定を表示するには、`pgactive.pgactive_get_table_replication_sets()` 関数を使用します。

# pgactive 関数リファレンス
<a name="pgactive-functions-reference"></a>

以下に、pgactive 関数のリストとそのパラメータ、戻り値、実用的な使用上の注意事項を示します。

## get\$1last\$1applied\$1xact\$1info
<a name="get-last-applied-xact-info"></a>

指定されたノードに最後に適用されたトランザクション情報を取得します。

**引数**  
+ sysid (テキスト) - タイムライン OID
+ dboid (OID)

**戻り型**  
以下を記録します。  
+ last\$1applied\$1xact\$1id (OID)
+ last\$1applied\$1xact\$1committs (タイムゾーン付きのタイムスタンプ)
+ last\$1applied\$1xact\$1at (タイムゾーン付きのタイムスタンプ)

**使用に関する注意事項**  
この関数を使用して、指定されたノードに最後に適用されたトランザクション情報を取得します。

## pgactive\$1apply\$1pause
<a name="pgactive-apply-pause"></a>

レプリケーション適用プロセスを一時停止します。

**引数**  
なし

**戻り型**  
boolean

**使用に関する注意事項**  
この関数を呼び出して、レプリケーション適用プロセスを一時停止します。

## pgactive\$1apply\$1resume
<a name="pgactive-apply-resume"></a>

レプリケーション適用プロセスを再開します。

**引数**  
なし

**戻り型**  
void

**使用に関する注意事項**  
この関数を呼び出して、レプリケーション適用プロセスを再開します。

## pgactive\$1is\$1apply\$1paused
<a name="pgactive-is-apply-paused"></a>

レプリケーション適用が現在一時停止されているかどうかを確認します。

**引数**  
なし

**戻り型**  
boolean

**使用に関する注意事項**  
この関数を使用して、レプリケーション適用が現在一時停止されているかどうかを確認します。

## pgactive\$1create\$1group
<a name="pgactive-create-group"></a>

スタンドアロンデータベースを初期ノードに変換して pgactive グループを作成します。



**引数**  
+ node\$1name (テキスト)
+ node\$1dsn (テキスト)
+ apply\$1delay integer DEFAULT NULL::integer - replication\$1sets text[] DEFAULT ARRAY[‘default’::text]

**戻り型**  
void

**使用に関する注意事項**  
スタンドアロンデータベースを初期ノードに変換して pgactive グループを作成します。この関数は、ノードを pgactive ノードに変換する前に、サニティチェックを実行します。この関数を使用する前に、PostgreSQL クラスターに pgactive バックグラウンドワーカーをサポートするのに十分な `max_worker_processes` が使用可能であることを確認してください。

## pgactive\$1detach\$1nodes
<a name="pgactive-detach-nodes"></a>

pgactive グループから指定されたノードを削除します。

**引数**  
+ p\$1nodes (text[])

**戻り型**  
void

**使用に関する注意事項**  
この関数を使用して、pgactive グループから指定されたノードを削除します。

## pgactive\$1exclude\$1table\$1replication\$1set
<a name="pgactive-exclude-table-replication-set"></a>

レプリケーションから特定のテーブルを除外します。

**引数**  
+ p\$1relation (regclass)

**戻り型**  
void

**使用に関する注意事項**  
この関数を使用して、レプリケーションから特定のテーブルを除外します。

## pgactive\$1get\$1replication\$1lag\$1info
<a name="pgactive-get-replication-lag-info"></a>

ノードの詳細、WAL ステータス、LSN 値など、詳細なレプリケーションラグ情報を取得します。

**引数**  
なし

**戻り型**  
SETOF record - node\$1name text - node\$1sysid text - application\$1name text - slot\$1name text - active boolean - active\$1pid integer - pending\$1wal\$1decoding bigint - Approximate size of WAL in bytes to be decoded on the sender node - pending\$1wal\$1to\$1apply bigint - Approximate size of WAL in bytes to be applied on receiving node - restart\$1lsn pg\$1lsn - confirmed\$1flush\$1lsn pg\$1lsn - sent\$1lsn pg\$1lsn - write\$1lsn pg\$1lsn - flush\$1lsn pg\$1lsn - replay\$1lsn pg\$1lsn

**使用に関する注意事項**  
この関数を呼び出して、ノードの詳細、WAL ステータス、LSN 値などのレプリケーションラグ情報を取得します。

## pgactive\$1get\$1stats
<a name="pgactive-get-stats"></a>

pgactive レプリケーションの統計を取得します。

**引数**  
なし

**戻り型**  
SETOF record - rep\$1node\$1id oid - rilocalid oid - riremoteid text - nr\$1commit bigint - nr\$1rollback bigint - nr\$1insert bigint - nr\$1insert\$1conflict bigint - nr\$1update bigint - nr\$1update\$1conflict bigint - nr\$1delete bigint - nr\$1delete\$1conflict bigint - nr\$1disconnect bigint

**使用に関する注意事項**  
この関数を使用して、pgactive レプリケーションの統計を取得します。

## pgactive\$1get\$1table\$1replication\$1sets
<a name="pgactive-get-table-replication-sets"></a>

特定のリレーションのレプリケーションセット設定を取得します。

**引数**  
+ リレーション (regclass)

**戻り型**  
SETOF レコード

**使用に関する注意事項**  
この関数を呼び出して、特定のリレーションのレプリケーションセット設定を取得します。

## pgactive\$1include\$1table\$1replication\$1set
<a name="pgactive-include-table-replication-set"></a>

レプリケーションに特定のテーブルを含めます。

**引数**  
+ p\$1relation (regclass)

**戻り型**  
void

**使用に関する注意事項**  
この関数を使用して、レプリケーションに特定のテーブルを含めます。

## pgactive\$1join\$1group
<a name="pgactive-join-group"></a>

既存の pgactive グループにノードを追加します。

**引数**  
+ node\$1name (テキスト)
+ node\$1dsn (テキスト)
+ join\$1using\$1dsn (テキスト)
+ apply\$1delay (整数、オプション)
+ replication\$1sets (text[]、デフォルト: ['default'])
+ bypass\$1collation\$1check (ブール値、デフォルト: false)
+ bypass\$1node\$1identifier\$1creation (ブール値、デフォルト: false)
+ bypass\$1user\$1tables\$1check (ブール値、デフォルト: false)

**戻り型**  
void

**使用に関する注意事項**  
この関数を呼び出して、既存の pgactive グループにノードを追加します。PostgreSQL クラスターに pgactive バックグラウンドワーカー用の十分な max\$1worker\$1processes があることを確認します。

## pgactive\$1remove
<a name="pgactive-remove"></a>

ローカルノードからすべての pgactive コンポーネントを削除します。

**引数**  
+ force (ブール値、デフォルト: false)

**戻り型**  
void

**使用に関する注意事項**  
この関数を呼び出して、ローカルノードからすべての pgactive コンポーネントを削除します。

## pgactive\$1snowflake\$1id\$1nextval
<a name="pgactive-snowflake-id-nextval"></a>

ノード固有の一意のシーケンス値を生成します。

**引数**  
+ regclass

**戻り型**  
bigint

**使用に関する注意事項**  
この関数を使用して、ノード固有の一意のシーケンス値を生成します。

## pgactive\$1update\$1node\$1conninfo
<a name="pgactive-update-node-conninfo"></a>

pgactive ノードの接続情報を更新します。

**引数**  
+ node\$1name\$1to\$1update (テキスト)
+ node\$1dsn\$1to\$1update (テキスト)

**戻り型**  
void

**使用に関する注意事項**  
この関数を使用して、pgactive ノードの接続情報を更新します。

## pgactive\$1wait\$1for\$1node\$1ready
<a name="pgactive-wait-for-node-ready"></a>

グループの作成または参加オペレーションの進行状況をモニタリングします。

**引数**  
+ タイムアウト (整数、デフォルト: 0)
+ progress\$1interval (整数、デフォルト: 60)

**戻り型**  
void

**使用に関する注意事項**  
この関数を呼び出して、グループの作成または参加オペレーションの進行状況をモニタリングします。

# アクティブ/アクティブレプリケーションの競合の処理
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-conflicts"></a>

`pgactive` 拡張は、クラスターごとではなく、データベースごとに機能します。`pgactive` を使用する各 DB インスタンスは、独立したインスタンスであり、あらゆるソースからのデータ変更を受け入れることができます。変更が DB インスタンスに送信されると、PostgreSQL は変更をローカルにコミットし、`pgactive` を使用して他の DB インスタンスに非同期に変更をレプリケートします。2 つの PostgreSQL DB インスタンスが同じレコードをほぼ同時に更新すると、競合が発生する可能性があります。

`pgactive` 拡張は、競合の検出と自動解決のためのメカニズムを提供します。両方の DB インスタンスでトランザクションがコミットされた時点のタイムスタンプを追跡し、最新のタイムスタンプで変更を自動的に適用します。また、`pgactive` 拡張は、`pgactive.pgactive_conflict_history` テーブルで競合が発生した場合もログに記録します。

`pgactive.pgactive_conflict_history` は継続的に増大します。パージポリシーを定義するとよいでしょう。これを行うには、一部のレコードを定期的に削除するか、この関係のパーティションスキームを定義します (その後で対象のパーティションをデタッチ、ドロップ、切り捨てることができます)。パージポリシーを定期的に実装するには、 `pg_cron` 拡張機能を使用するというオプションがあります。`pg_cron` 履歴テーブルの例については、「[PostgreSQL pg\$1cron 拡張機能を使用したメンテナンスのスケジュール](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL_pg_cron.html)」の次の情報を参照してください。

# アクティブ/アクティブレプリケーションでのシーケンスの処理
<a name="Appendix.PostgreSQL.CommonDBATasks.pgactive.handle-sequences"></a>

`pgactive` 拡張を使用した RDS for PostgreSQL DB インスタンスは、2 つの異なるシーケンスメカニズムを使用して固有の値を生成します。

**グローバルシーケンス**  
グローバルシーケンスを使用するには、`CREATE SEQUENCE` ステートメントを使用してローカルシーケンスを作成します。`usingnextval(seqname)` の代わりに `pgactive.pgactive_snowflake_id_nextval(seqname)` を使用すると、シーケンスの次の固有な値を取得できます。

次の例では、グローバルシーケンスを作成します。

```
app=> CREATE TABLE gstest (
      id bigint primary key,
      parrot text
    );
```

```
app=>CREATE SEQUENCE gstest_id_seq OWNED BY gstest.id;
```

```
app=> ALTER TABLE gstest \
      ALTER COLUMN id SET DEFAULT \
      pgactive.pgactive_snowflake_id_nextval('gstest_id_seq');
```

**分割シーケンス**  
分割ステップまたは分割シーケンスでは、通常の PostgreSQL シーケンスをノードごとに使用します。各シーケンスは同じ量ずつインクリメントされ、異なるオフセットから始まります。例えば、ステップ 100 の場合、ノード 1 は 101、201、301 などとしてシーケンスを生成し、ノード 2 は 102、202、302 などとしてシーケンスを生成します。このスキームは、ノードが長時間通信できない場合でも適切に機能しますが、設計者はスキーマを確立するときに最大ノード数を指定する必要があり、ノードごとの設定が必要になります。間違えると、シーケンスが重複しやすくなります。

次に示すように、ノードで目的のシーケンスを作成することで、このアプローチを `pgactive` で比較的簡単に設定できます。

```
CREATE TABLE some_table (generated_value bigint primary key);
```

```
app=> CREATE SEQUENCE some_seq INCREMENT 100 OWNED BY some_table.generated_value;
```

```
app=> ALTER TABLE some_table ALTER COLUMN generated_value SET DEFAULT nextval('some_seq');
```

次に、各ノードで `setval` を呼び出して、次のように異なるオフセットの開始値を指定します。

```
app=>
-- On node 1
SELECT setval('some_seq', 1);

-- On node 2
SELECT setval('some_seq', 2);
```

# pg\$1repack 拡張機能を使用して、テーブルやインデックスの膨張を抑制する
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack"></a>

`pg_repack` 拡張機能を使用して、`VACUUM FULL` の代わりとしてテーブルやインデックスの肥大化を取り除くことができます。このエクステンションは、RDS for PostgreSQL のバージョン 9.6.3 以降でサポートされています。`pg_repack` 拡張機能の詳細については、[GitHub プロジェクトのドキュメント](https://reorg.github.io/pg_repack/)をご覧ください。

`VACUUM FULL` とは異なり、`pg_repack` 拡張機能では、次の場合にテーブルの再構築オペレーション中に短期間だけ排他的ロック (AccessExclusiveLock) が必要です。
+ ログテーブルの初回作成 – 次の例に示すように、データの初回コピー中に発生した変更を記録するログテーブルが作成されます。

  ```
  postgres=>\dt+ repack.log_*
  List of relations
  -[ RECORD 1 ]-+----------
  Schema        | repack
  Name          | log_16490
  Type          | table
  Owner         | postgres
  Persistence   | permanent
  Access method | heap
  Size          | 65 MB
  Description   |
  ```
+ 最終スワップアンドドロップフェーズ。

再構築オペレーションの残りの部分で必要なのは、元のテーブルから新しいテーブルに行をコピーするための `ACCESS SHARE` ロックのみです。これにより、INSERT、UPDATE、DELETE オペレーションを通常どおりに進めることができます。

## 推奨事項
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack.Recommen"></a>

次の推奨事項は、`pg_repack` 拡張機能を使用してテーブルとインデックスの肥大化を取り除く場合に適用されます。
+ 業務時間外または他のデータベースアクティビティのパフォーマンスへの影響を最小限に抑えるために、メンテナンスウィンドウで再パックを実行します。
+ 再構築アクティビティ中にブロッキングセッションを注意深くモニタリングし、`pg_repack` をブロックする可能性のあるアクティビティが元のテーブルにないことを確認します。特に、元のテーブルで排他的ロックが必要なときは、最後のスワップアンドドロップフェーズ中にアクティビティがないことを確認します。詳細については、「[クエリをブロックしているものの特定](https://repost.aws/knowledge-center/rds-aurora-postgresql-query-blocked)」を参照してください。

  ブロッキングセッションが表示された場合は、慎重に検討した後、次のコマンドを使用してセッションを終了できます。これは、`pg_repack` の継続によって再構築を完了するのに役立ちます。

  ```
  SELECT pg_terminate_backend(pid);
  ```
+ トランザクション率が非常に高いシステムで `pg_repack's` ログテーブルから蓄積された変更を適用すると、適用プロセスが変更の速度に対して遅れる可能性があります。このような場合、`pg_repack` は適用プロセスを完了できません。詳細については、「[再パック中の新しいテーブルのモニタリング](#Appendix.PostgreSQL.CommonDBATasks.pg_repack.Monitoring)」を参照してください。インデックスが著しく肥大化している場合、代替の解決策は、インデックスのみの再パックを実行することです。これにより、VACUUM のインデックスクリーンアップサイクルをより速く完了させることもできます。

  PostgreSQL バージョン 12 の手動 VACUUM を使用してインデックスのクリーンアップフェーズをスキップできます。また、PostgreSQL バージョン 14 の緊急自動バキューム中は自動的にスキップされます。これにより、VACUUM はインデックスの肥大化を取り除くことなくより迅速に完了します。これは、循環 VACUUM の防止などの緊急時にのみ使用されます。詳細については、Amazon Aurora ユーザーガイドの「[インデックスの肥大化の回避](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html#AuroraPostgreSQL.diag-table-ind-bloat.AvoidinginIndexes)」を参照してください。

## 前提条件
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack.Prereq"></a>
+ テーブルには、PRIMARY KEY 制約または null 以外の UNIQUE 制約が必要です。
+ 拡張機能のバージョンは、クライアントとサーバーの両方で同じである必要があります。
+ RDS インスタンスに、肥大化がないテーブルの合計サイズ以上の `FreeStorageSpace` があることを確認します。例として、TOAST とインデックスを含むテーブルの合計サイズが 2TB で、テーブルの肥大化の合計が 1TB であるとします。必須の `FreeStorageSpace` は、次の計算によって返される値よりも大きくなければなりません。

   `2TB (Table size)` - `1TB (Table bloat)` = `1TB`

  次のクエリを使用してテーブルの合計サイズを確認し、`pgstattuple` を使用して肥大化を導き出すことができます。詳細については、Amazon Aurora ユーザーガイドの「[テーブルとインデックスの肥大化の診断](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html)」を参照してください。

  ```
  SELECT pg_size_pretty(pg_total_relation_size('table_name')) AS total_table_size;
  ```

  このスペースは、アクティビティの完了後に再利用されます。
+ RDS インスタンスに再パックオペレーションを処理するのに十分なコンピューティング容量と IO 容量があることを確認します。パフォーマンスのバランスを最適化するために、インスタンスクラスをスケールアップすることを検討してください。

**`pg_repack` 拡張機能を使用するには**

1. 次のコマンドを実行して、RDS for PostgreSQL DB インスタンスに `pg_repack` エクステンションをインストールします。

   ```
   CREATE EXTENSION pg_repack;
   ```

1. 次のコマンドを実行して、`pg_repack` によって作成されたテンポラリログテーブルへの書き込みアクセス権を付与します。

   ```
   ALTER DEFAULT PRIVILEGES IN SCHEMA repack GRANT INSERT ON TABLES TO PUBLIC;
   ALTER DEFAULT PRIVILEGES IN SCHEMA repack GRANT USAGE, SELECT ON SEQUENCES TO PUBLIC;
   ```

1. `pg_repack` クライアントユーティリティを使用してデータベースに接続します。`rds_superuser` 権限を持つアカウントを使用します。例として、`rds_test` ロールに `rds_superuser` 権限があるとします。次の構文は、`postgres` データベース内のすべてのテーブルインデックスを含む完全なテーブルに対して `pg_repack` を実行します。

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test -k postgres
   ```
**注記**  
-k オプションを使用して接続する必要があります。-a オプションはサポートされていません。

   `pg_repack` クライアントからのレスポンスにより、再パッケージされる DB インスタンスのテーブルに関する情報が提供されます。

   ```
   INFO: repacking table "pgbench_tellers"
   INFO: repacking table "pgbench_accounts"
   INFO: repacking table "pgbench_branches"
   ```

1. 次の構文は、`postgres` データベース内のインデックスを含む単一のテーブル `orders` を再パックします。

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test --table orders -k postgres
   ```

   次の構文では、`postgres` データベース内の `orders` テーブルのインデックスのみを再パックします。

   ```
   pg_repack -h db-instance-name.111122223333.aws-region.rds.amazonaws.com -U rds_test --table orders --only-indexes -k postgres
   ```

## 再パック中の新しいテーブルのモニタリング
<a name="Appendix.PostgreSQL.CommonDBATasks.pg_repack.Monitoring"></a>
+ データベースのサイズは、再パックのスワップアンドドロップフェーズまで、テーブルの合計サイズから肥大化を引いた数だけ増加します。データベースサイズの増加率をモニタリングし、再パックの速度を計算して、最初のデータ転送の完了にかかる時間を概算で見積もることができます。

  例えば、テーブルの合計サイズを 2TB、データベースのサイズを 4TB、テーブルの合計肥大化を 1TB とします。再パックオペレーションの最後に計算によって返されるデータベースの合計サイズ値は次のとおりです。

   `2TB (Table size)` \$1 `4 TB (Database size)` - `1TB (Table bloat)` = `5TB`

  再パックオペレーションの速度を概算で見積もるには、2 つの時点の間の増加率をバイト単位でサンプリングします。増加率が 1GB の場合、最初のテーブル構築オペレーションが完了するまでに 1000 分または 16.6 時間かかることがあります。最初のテーブル構築に加えて、`pg_repack` は蓄積された変更を適用する必要があります。所要時間は、進行中の変更と蓄積された変更の適用速度によって異なります。
**注記**  
`pgstattuple` 拡張機能を使用して、テーブルの肥大化を計算できます。詳細については、「[pgstattuple](https://www.postgresql.org/docs/current/pgstattuple.html)」を参照してください。
+ 再パックスキーマの下の `pg_repack's` ログテーブルの行数は、最初のロード後に新しいテーブルに適用される保留中の変更の量を表します。

  `pg_stat_all_tables` の `pg_repack's` ログテーブルをチェックして、新しいテーブルに適用される変更をモニタリングできます。`pg_stat_all_tables.n_live_tup` は、新しいテーブルに適用される保留中のレコードの数を示します。詳細については、「[pg\$1stat\$1all\$1tables](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW)」を参照してください。

  ```
  postgres=>SELECT relname,n_live_tup FROM pg_stat_all_tables WHERE schemaname = 'repack' AND relname ILIKE '%log%';
          
  -[ RECORD 1 ]---------
  relname    | log_16490
  n_live_tup | 2000000
  ```
+ `pg_stat_statements` 拡張機能を使用して、再パックオペレーションの各ステップにかかる時間を調べることができます。これは、本番環境で同じ再パックオペレーションを適用する準備に役立ちます。出力をさらに拡張するように `LIMIT` 句を調整できます。

  ```
  postgres=>SELECT
       SUBSTR(query, 1, 100) query,
       round((round(total_exec_time::numeric, 6) / 1000 / 60),4) total_exec_time_in_minutes
   FROM
       pg_stat_statements
   WHERE
       query ILIKE '%repack%'
   ORDER BY
       total_exec_time DESC LIMIT 5;
          
   query                                                                 | total_exec_time_in_minutes
  -----------------------------------------------------------------------+----------------------------
   CREATE UNIQUE INDEX index_16493 ON repack.table_16490 USING btree (a) |                     6.8627
   INSERT INTO repack.table_16490 SELECT a FROM ONLY public.t1           |                     6.4150
   SELECT repack.repack_apply($1, $2, $3, $4, $5, $6)                    |                     0.5395
   SELECT repack.repack_drop($1, $2)                                     |                     0.0004
   SELECT repack.repack_swap($1)                                         |                     0.0004
  (5 rows)
  ```

再パックは完全にアウトオブプレースオペレーションであるため、元のテーブルは影響を受けず、元のテーブルの復元を必要とする予期しない課題は予想されません。再パックが予期せず失敗した場合は、エラーの原因を調べて解決する必要があります。

問題が解決したら、テーブルが存在するデータベースに `pg_repack` 拡張機能を削除して再作成し、`pg_repack` ステップを再試行してください。さらに、コンピューティングリソースの可用性とテーブルの同時アクセシビリティは、再パックオペレーションをタイムリーに完了させる上で重要な役割を果たします。

# PLV8 拡張機能のアップグレードおよび使用
<a name="PostgreSQL.Concepts.General.UpgradingPLv8"></a>

PLV8 は、信頼できる JavaScript 言語の PostgreSQL 用エクステンションです。ストアドプロシージャ、トリガー、SQL から呼び出し可能なその他のプロシージャルコードに使用できます。この言語のエクステンションは、PostgreSQL のすべての最新リリースでサポートされています。

[PLV8](https://plv8.github.io/) を使用しており、PostgreSQL を新しい PLV8 バージョンにアップグレードする場合は、新しいエクステンションをすぐに利用できるようになります。次のステップを実行して、カタログメタデータを PLV8 の新しいバージョンと同期させます。これらの手順はオプションですが、メタデータ不一致の警告を回避するために実行することを強くお勧めします。

アップグレードプロセスでは、既存の PLV8 機能がすべて削除されます。そのため、アップグレードする前に、RDS for PostgreSQL DB インスタンスのスナップショットを作成しておくことをお勧めします。詳細については、「[Amazon RDS のシングル AZ DB インスタンスの DB スナップショットの作成](USER_CreateSnapshot.md)」を参照してください。

**重要**  
PostgreSQL バージョン 18 以降の Amazon RDS for PostgreSQL では、`plcoffee` および `plls` の PostgreSQL 拡張機能が廃止されます。エンジンバージョンがアップグレードされる場合に備えて、今後はアプリケーションで CoffeeScript や LiveScript を使用しないことをお勧めします。

**カタログメタデータを新しいバージョンの PLV8 と同期させるには**

1. 更新する必要があることを確認します。そのためには、インスタンスに接続されている間に以下のコマンドを実行します。

   ```
   SELECT * FROM pg_available_extensions WHERE name IN ('plv8','plls','plcoffee');
   ```

   インストールされているバージョンとしてデフォルトのバージョンより低いバージョンが表示された場合は、この手順を実行して、エクステンションを更新する必要があります。例えば、以下の結果セットは更新の必要があることを表します。

   ```
   name    | default_version | installed_version |                     comment
   --------+-----------------+-------------------+--------------------------------------------------
   plls    | 2.1.0           | 1.5.3             | PL/LiveScript (v8) trusted procedural language
   plcoffee| 2.1.0           | 1.5.3             | PL/CoffeeScript (v8) trusted procedural language
   plv8    | 2.1.0           | 1.5.3             | PL/JavaScript (v8) trusted procedural language
   (3 rows)
   ```

1. RDS for PostgreSQL DB インスタンスのスナップショットを作成していない場合は、作成してください。次のステップは、スナップショットの作成中も続行できます。

1. DB インスタンスの PLV8 関数の数を取得し、アップグレード後にすべて揃っていることを確認できるようにします。例えば次の SQL クエリ では、plv8、plcoffee、plls で記述されている関数の数が返ります。

   ```
   SELECT proname, nspname, lanname 
   FROM pg_proc p, pg_language l, pg_namespace n
   WHERE p.prolang = l.oid
   AND n.oid = p.pronamespace
   AND lanname IN ('plv8','plcoffee','plls');
   ```

1. pg\$1dump を使用して、スキーマのみのダンプファイルを作成します。例えば、クライアントマシンの `/tmp` ディレクトリに、ファイルを作成します。

   ```
   ./pg_dump -Fc --schema-only -U master postgres >/tmp/test.dmp
   ```

   この例では、以下のオプションを使用します。
   + `-Fc` – カスタム形式
   + -- スキーマのみ – スキーマの作成に必要なコマンド (ここでは関数) のみをダンプする
   + `-U` – RDS マスターユーザー名
   + `database` – DB インスタンスのデータベース名

   pg\$1dump の詳細については、「PostgreSQL ドキュメント」の「[pg\$1dump](https://www.postgresql.org/docs/current/static/app-pgdump.html )」を参照してください。

1. ダンプファイルに存在する "CREATE FUNCTION" DDL ステートメントを抽出します。次の例では `grep` コマンドを実行して、関数を作成する DDL ステートメントを抽出し、ファイルに保存します。この ddl は後続のステップで関数を再作成するために使用します。

   ```
   ./pg_restore -l /tmp/test.dmp | grep FUNCTION > /tmp/function_list
   ```

   pg\$1restore の詳細については、「PostgreSQL ドキュメント」の「[pg\$1restore](https://www.postgresql.org/docs/current/static/app-pgrestore.html)」を参照してください。

1. 関数およびエクステンションを削除します。次の例では、PLV8 ベースのオブジェクトを削除します。CASCADE オプションでは、すべての依存が削除されます。

   ```
   DROP EXTENSION plv8 CASCADE;
   ```

   plcoffee または plls に基づくオブジェクトが PostgreSQL インスタンスに含まれている場合は、それらのエクステンションに対してこのステップを繰り返します。

1. エクステンションを作成します。次の例では、plv8、plcoffee、plls のエクステンションが作成されます。

   ```
   CREATE EXTENSION plv8;
   CREATE EXTENSION plcoffee;
   CREATE EXTENSION plls;
   ```

1. ダンプファイルおよび "ドライバ" ファイルを使用して関数を作成します。

   次の例では、前に抽出した関数が再作成されます。

   ```
   ./pg_restore -U master -d postgres -Fc -L /tmp/function_list /tmp/test.dmp
   ```

1. 次のクエリを使用して、すべての関数が再作成されたことを確認します。

   ```
   SELECT * FROM pg_available_extensions WHERE name IN ('plv8','plls','plcoffee'); 
   ```

   PLV8 バージョン 2 では、次の行が結果セットに追加されます。

   ```
       proname    |  nspname   | lanname
   ---------------+------------+----------
    plv8_version  | pg_catalog | plv8
   ```

# PL/Rust を使って Rust 言語で PostgreSQL 関数を記述する
<a name="PostgreSQL.Concepts.General.Using.PL_Rust"></a>

PL/Rust は、PostgreSQL のための信頼できる Rust 言語エクステンションです。ストアドプロシージャ、関数、SQL から呼び出し可能なその他のプロシージャルコードに使用できます。PL/Rust 言語拡張は次のバージョンで利用可能です。
+ RDS for PostgreSQL 17.1 またはそれ以降の 17 バージョン
+ RDS for PostgreSQL 16.1 またはそれ以降の 16 バージョン
+ RDS for PostgreSQL 15.2-R2 またはそれ以降の 15 バージョン
+ RDS for PostgreSQL 14.9 またはそれ以降の 14 バージョン
+ RDS for PostgreSQL 13.12 またはそれ以降の 13 バージョン

詳細については、GitHub の「[PL/Rust](https://github.com/tcdi/plrust#readme)」を参照してください。

**Topics**
+ [PL/Rust の設定](#PL_Rust-setting-up)
+ [PL/Rust を使った関数の作成](#PL_Rust-create-function)
+ [PL/Rust の入ったクレートを使用する](#PL_Rust-crates)
+ [PL/Rust の制限事項](#PL_Rust-limitations)

## PL/Rust の設定
<a name="PL_Rust-setting-up"></a>

DB インスタンスに plrust 拡張機能をインストールするには、DBインスタンスに関連付けられた DB パラメータグループの `shared_preload_libraries` パラメータに plrust を追加します。plrust 拡張機能をインストールすると、関数を作成できます。

`shared_preload_libraries` パラメータを変更するには、DB インスタンスをカスタムパラメータグループに関連付ける必要があります。カスタム DB パラメータグループの作成については、「[Amazon RDS のパラメータグループ](USER_WorkingWithParamGroups.md)」を参照してください。

plust 拡張機能は、AWS マネジメントコンソール または AWS CLI を使用してインストールできます。

以下のステップでは、DB インスタンスがカスタム DB パラメータグループに関連付けられていることを前提としています。

### コンソール
<a name="PL_Rust-setting-up.CON"></a>

**plust 拡張機能を `shared_preload_libraries` パラメータにインストールする**

`rds_superuser` グループ (ロール) のメンバーであるアカウントを使用して、次のステップを完了します。

1. AWS マネジメントコンソール にサインインし、Amazon RDS コンソール ([https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)) を開きます。

1. ナビゲーションペインで、**データベース** を選択します。

1. DB インスタンスの名前を選択して、その詳細を表示します。

1. DB インスタンスの **[設定]** タブを開き、DB インスタンスパラメータグループのリンクを探します。

1. リンクを選択して、DB クラスターに関連付けられたカスタムパラメータを開きます。

1. **[パラメータ]** 検索フィールドに、`shared_pre` を入力して **`shared_preload_libraries`** パラメータを検索します。

1. プロパティ値にアクセスするには、**[Edit parameters]** (パラメータの編集) を選択します。

1. **[値]** フィールドのリストに plrust を追加します。値のリスト内の項目を区切るにはカンマを使用します。

1. DB インスタンスを再起動して、`shared_preload_libraries` パラメータの変更を有効にします。最初の再起動が完了するまでにさらに時間がかかる場合があります。

1. インスタンスが使用可能になったら、plrust が初期化されていることを確認します。`psql` を使用して DB インスタンスに接続し、次のコマンドを実行します。

   ```
   SHOW shared_preload_libraries;
   ```

   出力は以下のようになります。

   ```
   shared_preload_libraries 
   --------------------------
   rdsutils,plrust
   (1 row)
   ```

### AWS CLI
<a name="PL_Rust-setting-up-CLI"></a>

**shared\$1preload\$1libraries パラメータに pltrust 拡張機能をインストールする**

`rds_superuser` グループ (ロール) のメンバーであるアカウントを使用して、次のステップを完了します。

1. `shared_preload_libraries` パラメータに plrust を追加するには、[modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) AWS CLI コマンドを使用します。

   ```
   aws rds modify-db-parameter-group \
      --db-parameter-group-name custom-param-group-name \
      --parameters "ParameterName=shared_preload_libraries,ParameterValue=plrust,ApplyMethod=pending-reboot" \
      --region aws-region
   ```

1. [reboot-db-instance](https://docs.aws.amazon.com/cli/latest/reference/rds/reboot-db-instance) AWS CLI コマンドを使用して DB インスタンスを再起動し、plrust ライブラリを初期化します。最初の再起動が完了するまでにさらに時間がかかる場合があります。

   ```
   aws rds reboot-db-instance \
       --db-instance-identifier your-instance \
       --region aws-region
   ```

1. インスタンスが使用可能になったら、plrust が初期化されていることを確認できます。`psql` を使用して DB インスタンスに接続し、次のコマンドを実行します。

   ```
   SHOW shared_preload_libraries;
   ```

   出力は以下のようになります。

   ```
   shared_preload_libraries
   --------------------------
   rdsutils,plrust
   (1 row)
   ```

## PL/Rust を使った関数の作成
<a name="PL_Rust-create-function"></a>

PL/Rust は関数を動的ライブラリとしてコンパイルし、ロードして実行します。

次の Rust 関数は、配列から複数を除外します。

```
postgres=> CREATE LANGUAGE plrust;
CREATE EXTENSION
```

```
CREATE OR REPLACE FUNCTION filter_multiples(a BIGINT[], multiple BIGINT) RETURNS BIGINT[]
    IMMUTABLE STRICT
    LANGUAGE PLRUST AS
$$
    Ok(Some(a.into_iter().filter(|x| x.unwrap() % multiple != 0).collect()))
$$;
        
WITH gen_values AS (
SELECT ARRAY(SELECT * FROM generate_series(1,100)) as arr)
SELECT filter_multiples(arr, 3)
from gen_values;
```

## PL/Rust の入ったクレートを使用する
<a name="PL_Rust-crates"></a>

RDS for PostgreSQL バージョン 16.3-R2 以降、15.7-R2 以降の 15 バージョン、14.12-R2 以降の 14 バージョン、および 13.15-R2 以降の 13 バージョンでは、PL/Rust は追加のクレートをサポートしています。
+ `url` 
+ `regex` 
+ `serde` 
+ `serde_json` 

RDS for PostgreSQL バージョン 15.5-R2 以降、14.10-R2 以降の 14 バージョン、および 13.13-R2 以降の 13 バージョンでは、PL/Rust は 2 つの追加のクレートをサポートしています。
+ `croaring-rs` 
+ `num-bigint` 

Amazon RDS for PostgreSQL バージョン 15.4、14.9、13.12 以降、PL/Rust は、次のクレートをサポートします。
+ `aes` 
+ `ctr` 
+ `rand` 

これらのクレートではデフォルト機能のみがサポートされています。新しい RDS for PostgreSQL バージョンには、更新されたバージョンのクレートが含まれているため、古いバージョンのクレートはサポートされなくなる可能性があります。

メジャーバージョンアップグレードを行う際のベストプラクティスに従って、お使いの PL/Rust 関数が新しいメジャーバージョンと互換性があるかどうかをテストしてください。詳細については、「Amazon RDS ユーザーガイド」のブログ「[Amazon RDS を PostgreSQL のメジャーバージョンとマイナーバージョンにアップグレードするためのベストプラクティス](https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/)」と「[Amazon RDS の PostgreSQL DB エンジンのアップグレード](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.PostgreSQL.html)」を参照してください。

PL/Rust 関数を作成する際の依存関係の使用例については、「[依存関係を使う](https://tcdi.github.io/plrust/use-plrust.html#use-dependencies)」を参照してください。

## PL/Rust の制限事項
<a name="PL_Rust-limitations"></a>

デフォルトでは、データベースユーザーは PL/Rust を使用できません。PL/Rust へのアクセスを提供するには、rds\$1superuser 権限を持つユーザーとして接続し、次のコマンドを実行します。

```
postgres=> GRANT USAGE ON LANGUAGE PLRUST TO user;
```

# PostGIS 拡張機能を使用した空間データの管理
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS"></a>

PostGIS は PostgreSQL の拡張機能であり、空間情報の保存と管理に使用します。PostGIS の詳細については、「[Postgis.net](https://postgis.net/)」を参照してください。

バージョン 10.5 以降の PostgreSQL では、PostGIS がマップボックスのベクトルタイルデータを操作するために使用する libprotobuf 1.3.0 ライブラリがサポートされています。

PostGIS 拡張機能のセットアップには、`rds_superuser` 権限が必要です。PostGIS 拡張機能と空間データを管理するためのユーザー (ロール) を作成することをお勧めします。PostGIS 拡張機能とその関連コンポーネントは PostgreSQL に数千もの関数を追加します。ユースケースに適している場合は、PostGIS エクステンションを独自のスキーマで作成することを検討してください。次の例は、拡張機能を独自のデータベースにインストールする方法を示していますが、これは必須ではありません。

**Topics**
+ [ステップ 1: PostGIS 拡張機能を管理するユーザー (ロール) を作成する](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Connect)
+ [ステップ 2: PostGIS エクステンションを読み込む](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.LoadExtensions)
+ [ステップ 3: 拡張機能スキーマの所有権を移管する](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferOwnership)
+ [ステップ 4: PostGIS テーブルの所有権を移管する](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferObjects)
+ [ステップ 5: エクステンションをテストする](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Test)
+ [ステップ 6: PostGIS 拡張機能を更新する](#Appendix.PostgreSQL.CommonDBATasks.PostGIS.Update)
+ [PostGIS 拡張バージョン](#CHAP_PostgreSQL.Extensions.PostGIS)
+ [PostGIS 2 から PostGIS 3 へのアップグレード](#PostgreSQL.Extensions.PostGIS.versions.upgrading.2-to-3)

## ステップ 1: PostGIS 拡張機能を管理するユーザー (ロール) を作成する
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.Connect"></a>

まず、`rds_superuser` 権限があるユーザーとして RDS for PostgreSQL DB インスタンスに接続します。インスタンスの設定時にデフォルトの名前を保持している場合は、次のように `postgres` として接続します。

```
psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
```

PostGIS 拡張機能を管理する別のロール (ユーザー) を作成します。

```
postgres=>  CREATE ROLE gis_admin LOGIN PASSWORD 'change_me';
CREATE ROLE
```

このロールに `rds_superuser` 権限を付与して、ロールが拡張機能をインストールできるようにします。

```
postgres=> GRANT rds_superuser TO gis_admin;
GRANT
```

PostGIS アーティファクトに使用するデータベースを作成します。この手順は省略可能です。または、ユーザーデータベースに PostGIS 拡張機能用のスキーマを作成することもできますが、これも必須ではありません。

```
postgres=> CREATE DATABASE lab_gis;
CREATE DATABASE
```

`gis_admin` に `lab_gis` データベース上のすべての特権を付与します。

```
postgres=> GRANT ALL PRIVILEGES ON DATABASE lab_gis TO gis_admin;
GRANT
```

セッションを終了し、RDS for PostgreSQL DB インスタンスに `gis_admin` として再接続します。

```
postgres=> psql --host=111122223333.aws-region.rds.amazonaws.com --port=5432 --username=gis_admin --password --dbname=lab_gis
Password for user gis_admin:...
lab_gis=>
```

次の手順の説明に従って、拡張機能のセットアップを続けます。

## ステップ 2: PostGIS エクステンションを読み込む
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.LoadExtensions"></a>

PostGIS 拡張機能には複数の関連する拡張機能があり、それらが連携することで地理空間機能を提供しています。ユースケースによっては、このステップで作成した拡張機能の一部が必要ない場合があります。

`CREATE EXTENSION` ステートメントを使用して PostGIS エクステンションをロードします。

```
CREATE EXTENSION postgis;
CREATE EXTENSION
CREATE EXTENSION postgis_raster;
CREATE EXTENSION
CREATE EXTENSION fuzzystrmatch;
CREATE EXTENSION
CREATE EXTENSION postgis_tiger_geocoder;
CREATE EXTENSION
CREATE EXTENSION postgis_topology;
CREATE EXTENSION
CREATE EXTENSION address_standardizer_data_us;
CREATE EXTENSION
```

次の例に示されている SQL クエリを実行すると、拡張子とその所有者がリストアップされ、結果を確認することができます。

```
SELECT n.nspname AS "Name",
  pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner"
  FROM pg_catalog.pg_namespace n
  WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
  ORDER BY 1;
List of schemas
     Name     |   Owner
--------------+-----------
 public       | postgres
 tiger        | rdsadmin
 tiger_data   | rdsadmin
 topology     | rdsadmin
(4 rows)
```

## ステップ 3: 拡張機能スキーマの所有権を移管する
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferOwnership"></a>

ALTER SCHEMA ステートメント使用して、`gis_admin` ロールにスキーマの所有権を移転します。

```
ALTER SCHEMA tiger OWNER TO gis_admin;
ALTER SCHEMA
ALTER SCHEMA tiger_data OWNER TO gis_admin; 
ALTER SCHEMA
ALTER SCHEMA topology OWNER TO gis_admin;
ALTER SCHEMA
```

次の SQL クエリを実行して、所有権の変更を確認できます。または、psql コマンドラインの `\dn` メタコマンドを使用します。

```
SELECT n.nspname AS "Name",
  pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner"
  FROM pg_catalog.pg_namespace n
  WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
  ORDER BY 1;

       List of schemas
     Name     |     Owner
--------------+---------------
 public       | postgres
 tiger        | gis_admin
 tiger_data   | gis_admin
 topology     | gis_admin
(4 rows)
```

## ステップ 4: PostGIS テーブルの所有権を移管する
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.TransferObjects"></a>

**注記**  
PostGIS 関数の所有権を変更しないでください。PostGIS の適切な運用と今後のアップグレードでは、これらの関数が元の所有権を保持する必要があります。PostGIS アクセス許可の詳細については、「[PostgreSQL Security](https://postgis.net/workshops/postgis-intro/security.html)」を参照してください。

次の関数を使用して、`gis_admin` ロールに PostGIS テーブルの所有権を移管します。psql プロンプトから次のステートメントを実行して関数を作成します。

```
CREATE FUNCTION exec(text) returns text language plpgsql volatile AS $f$ BEGIN EXECUTE $1; RETURN $1; END; $f$;
CREATE FUNCTION
```

続いて、次のクエリを実行して `exec` 関数を実行すると、ステートメントが実行されてアクセス許可が変更されます。

```
SELECT exec('ALTER TABLE ' || quote_ident(s.nspname) || '.' || quote_ident(s.relname) || ' OWNER TO gis_admin;')
  FROM (
    SELECT nspname, relname
    FROM pg_class c JOIN pg_namespace n ON (c.relnamespace = n.oid) 
    WHERE nspname in ('tiger','topology') AND
    relkind IN ('r','S','v') ORDER BY relkind = 'S')
s;
```

## ステップ 5: エクステンションをテストする
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.Test"></a>

スキーマ名の指定を不要とするには、次のコマンドを使用して検索パスに `tiger` スキーマを追加します。

```
SET search_path=public,tiger;
SET
```

次の SELECT ステートメントを使用して、`tiger` スキーマをテストします。

```
SELECT address, streetname, streettypeabbrev, zip
 FROM normalize_address('1 Devonshire Place, Boston, MA 02109') AS na;
address | streetname | streettypeabbrev |  zip
---------+------------+------------------+-------
       1 | Devonshire | Pl               | 02109
(1 row)
```

この拡張機能の詳細については、PostGIS ドキュメントの「[Tiger Geocoder](https://postgis.net/docs/Extras.html#Tiger_Geocoder)」を参照してください。

次の `topology` ステートメントを使用して `SELECT` スキーマへのアクセスをテストします。これにより、`createtopology` 関数を呼び出して、指定された空間参照識別子 (26986) とデフォルトの許容誤差 (0.5) を持つ新しいトポロジーオブジェクト (my\$1new\$1topo) を登録します。詳細については、PostGIS ドキュメントの「[CreateTopology](https://postgis.net/docs/CreateTopology.html)」を参照してください。

```
SELECT topology.createtopology('my_new_topo',26986,0.5);
 createtopology
----------------
              1
(1 row)
```

## ステップ 6: PostGIS 拡張機能を更新する
<a name="Appendix.PostgreSQL.CommonDBATasks.PostGIS.Update"></a>

PostgreSQL の新しいリリースでは、それぞれのリリースと互換性のある 1 つまたは複数のバージョンの PostGIS 拡張機能をサポートしています。PostgreSQL エンジンを新しいバージョンにアップグレードしても、PostGIS 拡張機能は自動的にアップグレードされません。PostgreSQL エンジンをアップグレードする前に、通常 PostGIS を現在の PostgreSQL バージョンで使用可能な最新バージョンにアップグレードします。詳細については、「[PostGIS 拡張バージョン](#CHAP_PostgreSQL.Extensions.PostGIS)」を参照してください。

PostgreSQL エンジンのアップグレード後、PostGIS 拡張機能を再度アップグレードして、新しくアップグレードした PostgreSQL エンジンバージョンでサポートされているバージョンにアップグレードします。PostgreSQL のアップグレードの詳細については、「 [RDS for PostgreSQL のメジャーバージョンアップグレードを実行する方法](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md)」を参照してください。

 RDS for PostgreSQL DB インスタンスでは、利用可能な PostGIS 拡張機能のバージョンアップを常時確認できます。そうするには、以下のコマンドを実行します。この関数は、PostGIS 2.5.0 以降のバージョンで使用できます。

```
SELECT postGIS_extensions_upgrade();
```

アプリケーションが最新で PostGIS バージョンがサポートされていない場合でも、次のように、メジャーバージョンで使用できる古いバージョンの PostGIS をインストールできます。

```
CREATE EXTENSION postgis VERSION "2.5.5";
```

古いバージョンから特定の PostGIS バージョンにアップグレードする場合は、次のコマンドも使用できます。

```
ALTER EXTENSION postgis UPDATE TO "2.5.5";
```

アップグレード前のバージョンによっては、この関数をもう一度実行する必要があります。初期に関数を実行した結果によって、追加のアップグレード関数が必要かどうかが決まります。例えば、PostGIS 2 から PostGIS 3 にアップグレードする場合がこれに該当します。(詳しくは、「[PostGIS 2 から PostGIS 3 へのアップグレード](#PostgreSQL.Extensions.PostGIS.versions.upgrading.2-to-3)」を参照してください。)

PostgreSQL エンジンのメジャーアップグレードの準備のためにこの拡張機能をアップグレードした場合は、他の準備作業を継続できます。詳細については、「[RDS for PostgreSQL のメジャーバージョンアップグレードを実行する方法](USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process.md)」を参照してください。

## PostGIS 拡張バージョン
<a name="CHAP_PostgreSQL.Extensions.PostGIS"></a>

に記載されている PostGIS など、すべての拡張機能バージョンをインストールすることをお勧めします。「[Amazon RDS for PostgreSQL リリースノート](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html)」の *Amazon RDS for PostgreSQL の拡張バージョン*。リリースで利用可能なバージョンのリストを取得するには、次のコマンドを使用します。

```
SELECT * FROM pg_available_extension_versions WHERE name='postgis';
```

バージョン情報は、*Amazon RDS for PostgreSQL リリースノート*の次のセクションで確認できます。
+ [Amazon RDS でサポートされる PostgreSQL バージョン 16 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-16x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 15 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-15x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 14 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-14x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 13 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-13x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 12 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-12x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 11 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-11x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 10 の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-101x)
+ [Amazon RDS でサポートされる PostgreSQL バージョン 9.6.x の拡張機能](https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html#postgresql-extensions-96x)

## PostGIS 2 から PostGIS 3 へのアップグレード
<a name="PostgreSQL.Extensions.PostGIS.versions.upgrading.2-to-3"></a>

バージョン 3.0 以降、PostGIS ラスター機能は別の `postgis_raster` という拡張機能になりました。この拡張機能には、独自のインストールとアップグレードパスがあります。これにより、ラスター画像処理に必要な多くの関数、データ型などのアーティファクトがコア `postgis` 拡張機能から削除されます。つまり、ユースケースにラスター処理が必要ない場合は、`postgis_raster` 拡張機能をインストールする必要はありません。

次のアップグレード例では、最初のアップグレードコマンドは、ラスター機能を `postgis_raster` 拡張機能に展開します。次に、`postgis_raster` を新しいバージョンにアップグレードするには 2 つ目のアップグレードコマンドが必要です。

**PostGIS 2 から PostGIS 3 にアップグレードするには**

1. お使いの の PostgreSQL バージョンで利用可能な PostGIS のデフォルトバージョンを確認します。RDS for PostgreSQL DB インスタンス。確認するために、以下のクエリを実行します。

   ```
   SELECT * FROM pg_available_extensions
       WHERE default_version > installed_version;
     name   | default_version | installed_version |                          comment
   ---------+-----------------+-------------------+------------------------------------------------------------
    postgis | 3.1.4           | 2.3.7             | PostGIS geometry and geography spatial types and functions
   (1 row)
   ```

1. 、RDS for PostgreSQL DB インスタンスの各データベースにインストールされている PostGIS のバージョンを確認します。つまり、各ユーザーデータベースを次のようにクエリします。

   ```
   SELECT
       e.extname AS "Name",
       e.extversion AS "Version",
       n.nspname AS "Schema",
       c.description AS "Description"
   FROM
       pg_catalog.pg_extension e
       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
       LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid
       AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass
   WHERE
       e.extname LIKE '%postgis%'
   ORDER BY
       1;
     Name   | Version | Schema |                             Description
   ---------+---------+--------+---------------------------------------------------------------------
    postgis | 2.3.7   | public | PostGIS geometry, geography, and raster spatial types and functions
   (1 row)
   ```

   このようにデフォルトバージョン (PostGIS 3.1.4) とインストールされているバージョン (PostGIS 2.3.7) が一致しない場合は、PostGIS 拡張機能をアップグレードする必要があることになります。

   ```
   ALTER EXTENSION postgis UPDATE;
   ALTER EXTENSION
   WARNING: unpackaging raster
   WARNING: PostGIS Raster functionality has been unpackaged
   ```

1. 次のクエリを実行して、ラスター機能が独自のパッケージに組み込まれていることを確認します。

   ```
   SELECT
       probin,
       count(*)
   FROM
       pg_proc
   WHERE
       probin LIKE '%postgis%'
   GROUP BY
       probin;
             probin          | count
   --------------------------+-------
    $libdir/rtpostgis-2.3    | 107
    $libdir/postgis-3        | 487
   (2 rows)
   ```

   出力を確認すれば、バージョンの間にまだ差があることがわかります。PostGIS 関数はバージョン 3 (postgis-3) で、ラスター関数 (rtpostgis) はバージョン 2 (rtpostgis-2.3) です。アップグレードを完了するには、次のようにアップグレードコマンドを再度実行します。

   ```
   postgres=> SELECT postgis_extensions_upgrade();
   ```

   警告メッセージは無視しても問題ありません。次のクエリを再度実行して、アップグレードが完了していることを確認します。PostGIS と関連するすべての拡張機能に対してアップグレードが必要と表示されていなければ、アップグレードは完了です。

   ```
   SELECT postgis_full_version();
   ```

1. 次のクエリを使用して、完了したアップグレードプロセスと個別にパッケージ化された拡張機能を確認し、それぞれのバージョンが一致していることを確認します。

   ```
   SELECT
       e.extname AS "Name",
       e.extversion AS "Version",
       n.nspname AS "Schema",
       c.description AS "Description"
   FROM
       pg_catalog.pg_extension e
       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
       LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid
           AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass
   WHERE
       e.extname LIKE '%postgis%'
   ORDER BY
       1;
         Name      | Version | Schema |                             Description
   ----------------+---------+--------+---------------------------------------------------------------------
    postgis        | 3.1.5   | public | PostGIS geometry, geography, and raster spatial types and functions
    postgis_raster | 3.1.5   | public | PostGIS raster types and functions
   (2 rows)
   ```

   出力には、PostGIS 2 拡張機能が PostGIS 3 にアップグレードされ、`postgis` と現在は分離された `postgis_raster` 拡張機能の両方がバージョン 3.1.5 であることが表示されます。

このアップグレード完了後にラスター機能を使用する予定がない場合は、次のように拡張機能を削除できます。

```
DROP EXTENSION postgis_raster;
```