

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 pglogical 跨執行個體同步資料
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical"></a>

所有目前可用的 RDS for PostgreSQL 版本都支援 `pglogical` 延伸模組。pglogical 延伸模組早於 PostgreSQL 在第 10 版中引入的功能，其類似於邏輯複寫功能。如需詳細資訊，請參閱 [為 Amazon RDS for PostgreSQL 執行邏輯複寫](PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.md)。

`pglogical` 延伸模組支援在兩個或以上 之間進行邏輯複寫。RDS for PostgreSQL 資料庫執行個體。它也支援在不同的 PostgreSQL 版本之間，以及在 RDS for PostgreSQL 資料庫執行個體和 Aurora PostgreSQL 資料庫叢集上執行的資料庫之間進行複寫。`pglogical` 延伸模組會使用發佈-訂閱模型，將資料表和其他物件 (例如序列) 的變更從發佈者複製到訂閱者。它依賴複寫槽，以確保變更從發佈者節點同步到訂閱者節點，其定義如下。
+ *發佈者節點*是 RDS for PostgreSQL 資料庫執行個體，其是要複寫到其他節點的資料來源。發佈者節點定義要在發佈集中複製的資料表。
+ *訂閱者節點*是 RDS for PostgreSQL 資料庫執行個體，其會從發佈者接收 WAL 更新。訂閱者會建立訂閱以連線至發佈者，並取得解碼的 WAL 資料。訂閱者建立訂閱時，系統會在發佈者節點上建立複寫槽。

您可以在以下內容中找到如何設定 `pglogical` 延伸模組的相關資訊。

**Topics**
+ [pglogical 延伸模組的需求和限制](#Appendix.PostgreSQL.CommonDBATasks.pglogical.requirements-limitations)
+ [設定 pglogical 延伸模組](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md)
+ [針對 RDS for PostgreSQL 資料庫執行個體設定邏輯複寫](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 版及更新版本) 內建邏輯複寫功能不支援的功能，例如雙向複寫。如需詳細資訊，請參閱[使用 pglogical 進行 PostgreSQL 雙向複寫](https://aws.amazon.com/blogs/database/postgresql-bi-directional-replication-using-pglogical/)。

# 設定 pglogical 延伸模組
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup"></a>

若要在 RDS for PostgreSQL 資料庫執行個體上設定 `pglogical` 延伸模組，請將 `pglogical` 新增至下列群組上的共用程式庫：RDS for PostgreSQL 資料庫執行個體的自訂資料庫參數群組。您亦需將 `rds.logical_replication` 參數的值設為 `1`，以開啟邏輯解碼。最後，您可以在資料庫中建立延伸模組。您可以使用 AWS 管理主控台 或 AWS CLI 進行這些任務。

您必須具有做為 `rds_superuser` 角色的許可，才能執行這些任務。

以下步驟假設您的 RDS for PostgreSQL 資料庫執行個體與自訂資料庫參數群組相關聯。如需建立自訂資料庫叢集參數群組的相關資訊，請參閱 [Amazon RDS 的參數群組](USER_WorkingWithParamGroups.md)。

## 主控台
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.CON"></a>

**設定 pglogical 延伸模組**

1. 登入 AWS 管理主控台 ，並在 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)：// 開啟 Amazon RDS 主控台。

1. 在導覽窗格中，選擇您的 RDS for PostgreSQL 資料庫執行個體。

1. 針對您的 開啟 **Configuration** (組態) 索引標籤。RDS for PostgreSQL 資料庫執行個體。在執行個體詳細資訊之間，尋找 **Parameter group** (參數群組) 連結。

1. 選擇連結以開啟與 相關聯的自訂參數。RDS for PostgreSQL 資料庫執行個體。

1. 在 **Parameters** (參數) 搜尋欄位中，輸入 `shared_pre` 以尋找 `shared_preload_libraries` 參數。

1. 選擇 **Edit parameters** (編輯參數) 以存取屬性值。

1. 在 **Values** (值) 欄位中，將 `pglogical` 新增至清單。使用逗號區隔值清單中的項目。  
![\[已新增 pglogical 之 shared_preload_libraries 參數的影像。\]](http://docs.aws.amazon.com/zh_tw/AmazonRDS/latest/UserGuide/images/apg_rpg_shared_preload_pglogical.png)

1. 尋找 `rds.logical_replication` 參數並將其設為 `1`，以開啟邏輯複寫。

1. 重新啟動 RDS for PostgreSQL 資料庫執行個體，讓您的變更生效。

1. 當執行個體可用時，您可以使用 `psql` (或 pgAdmin) 連線至 RDS for PostgreSQL 資料庫執行個體。。

   ```
   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. 選擇**儲存變更**。

1. 前往 [https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/)，開啟 Amazon RDS 主控台。

1. 從資料庫清單中選擇 RDS for PostgreSQL 資料庫執行個體以選取它，然後從 Actions (動作) 功能表中選擇 **Reboot** (重新啟動)。

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

**設定 pglogical 延伸模組**

若要使用 設定 pglogical AWS CLI，您可以呼叫 [modify-db-parameter-group](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-parameter-group.html) 操作來修改自訂參數群組中的特定參數，如下列程序所示。

1. 使用下列 AWS CLI 命令將 `pglogical`新增至 `shared_preload_libraries` 參數。

   ```
   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 資料庫執行個體。

   ```
   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 資料庫執行個體，以便初始化 pglogical 程式庫。

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

1. 當執行個體可用時，請使用 `psql` 連線至 RDS for PostgreSQL 資料庫執行個體。。

   ```
   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 資料庫執行個體。

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

# 針對 RDS for PostgreSQL 資料庫執行個體設定邏輯複寫
<a name="Appendix.PostgreSQL.CommonDBATasks.pglogical.setup-replication"></a>

下列程序說明如何在兩個 RDS for PostgreSQL 資料庫執行個體之間啟動邏輯複寫。這些步驟假設來源 (發佈者) 和目標 (訂閱者) 都已設定 `pglogical` 延伸模組，如 [設定 pglogical 延伸模組](Appendix.PostgreSQL.CommonDBATasks.pglogical.basic-setup.md) 中所述。

**注意**  
訂閱者節點的 `node_name` 不能以 `rds` 開頭。

**建立發佈者節點並定義要複製的資料表**

這些步驟假設您的 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 資料庫執行個體識別為發佈者節點，如下所示。

   ```
   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 資料庫執行個體已使用 `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 資料庫執行個體上，建立存在於發佈者上的相同資料表。在此範例中，資料表是 `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 資料庫執行個體識別為訂閱者節點，如下所示。

   ```
   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 資料庫執行個體執行主要版本升級之前，您必須捨棄所有複寫槽，即使是未作用中的複寫槽也一樣。建議您暫時從發佈者節點轉移資料庫交易、捨棄複寫槽、升級 RDS for PostgreSQL 資料庫執行個體，然後重新建立並重新啟動複寫。

複寫槽僅託管於發佈者節點上。邏輯複寫案例中的 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` 函數。請注意作用中資料欄中的值。通常，這會傳回 `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)
  ```

**檢查訂閱者節點**

在訂閱者節點上，您可以採取三種不同的方式來檢查複寫的狀態。
+ 查看訂閱者節點上的 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 資料庫執行個體執行主要版本升級之前，您必須捨棄執行個體上的複寫槽。主要版本升級預先檢查程序會通知您，除非捨棄複寫槽，否則升級無法繼續進行。

若要從 RDS for PostgreSQL 資料庫執行個體中捨棄複寫槽，請先捨棄訂閱，然後捨棄複寫槽。

若要識別已使用 `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` 這類參數用來處理更新衝突。對從發佈者訂閱變更的相同資料表進行本機變更時，可能會出現衝突。在各種案例期間 (例如雙向複寫或從相同發佈者複寫多個訂閱者時)，也會發生衝突。如需詳細資訊，請參閱[使用 pglogical 進行 PostgreSQL 雙向複寫](https://aws.amazon.com/blogs/database/postgresql-bi-directional-replication-using-pglogical/)。


| 參數 | Description | 
| --- | --- | 
| 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 | 使用 SPI (伺服器程式設計介面) 而不是低階 API 來套用變更。設為 '1' 以開啟、設為 '0' 以關閉。如需 SPI 的詳細資訊，請參閱 PostgreSQL 文件中的 [Server Programming Interface](https://www.postgresql.org/docs/current/spi.html) (伺服器程式設計介面)。 | 