★PostgreSQLカンファレンス2025 11月21日開催/チケット販売中★
他のバージョンの文書 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

29.3. 論理レプリケーションのフェイルオーバー #

パブリッシャーノードがダウンした場合でも、サブスクライバーノードがパブリッシャーノードからのデータの複製を継続できるようにするには、パブリッシャーノードに対応する物理スタンバイが必要です。 サブスクリプションに対応するプライマリサーバの論理スロットは、サブスクリプションの作成時にfailover = trueを指定することで、スタンバイサーバと同期させることができます。 詳細は47.2.3を参照してください。 failoverパラメータを有効にすると、スタンバイ昇格後のサブスクリプションのシームレスな移行が保証されます。 サブスクリプションは新しいプライマリサーバ上のパブリケーションへのサブスクライブを継続できます。

スロット同期ロジックは非同期にコピーを行うため、フェイルオーバーが発生する前にレプリケーションスロットがスタンバイサーバに同期されているかを確認する必要があります。 フェイルオーバーの成功を保証するためには、スタンバイサーバはサブスクライバーよりも先行していなければいけません。 これはsynchronized_standby_slotsを設定することで実現できます。

スタンバイサーバがフェイルオーバーの準備ができていることを確認するためには、次の手順に従って、サブスクライバーに必要なすべての論理レプリケーションスロットがスタンバイサーバと同期されていることを検証します。

  1. サブスクライバーノードで、次のSQLを使用して、昇格する予定のスタンバイに同期する必要があるレプリケーションスロットを特定します。 このクエリは、フェイルオーバーが有効になっているサブスクリプションと関連付けられている、関連するレプリケーションスロットを返します。

    test_sub=# SELECT
                   array_agg(quote_literal(s.subslotname)) AS slots
               FROM  pg_subscription s
               WHERE s.subfailover AND
                     s.subslotname IS NOT NULL;
     slots
    -------
     {'sub1','sub2','sub3'}
    (1 row)
    
  2. サブスクライバーノードで、次のSQLを使用して、昇格する予定のスタンバイに同期する必要があるテーブル同期スロットを特定します。 このクエリは、フェイルオーバーが有効になっているサブスクリプションを持つ各データベースで実行する必要があります。 テーブル同期スロットは、テーブル同期が終了している場合にのみ同期されることに注意してください(51.55を参照)。 その他の場合では、テーブル同期スロットが同期されることを保証する必要はありません。これらは破棄されるか、新しいプライマリサーバで再作成されるためです。

    test_sub=# SELECT
                   array_agg(quote_literal(slot_name)) AS slots
               FROM
               (
                   SELECT CONCAT('pg_', srsubid, '_sync_', srrelid, '_', ctl.system_identifier) AS slot_name
                   FROM pg_control_system() ctl, pg_subscription_rel r, pg_subscription s
                   WHERE r.srsubstate = 'f' AND s.oid = r.srsubid AND s.subfailover
               );
     slots
    -------
     {'pg_16394_sync_16385_7394666715149055164'}
    (1 row)
    
  3. 上記で特定した論理レプリケーションスロットがスタンバイに存在し、フェイルオーバーの準備ができていることを確認します。

    test_standby=# SELECT slot_name, (synced AND NOT temporary AND invalidation_reason IS NULL) AS failover_ready
                   FROM pg_replication_slots
                   WHERE slot_name IN
                       ('sub1','sub2','sub3', 'pg_16394_sync_16385_7394666715149055164');
      slot_name                                 | failover_ready
    --------------------------------------------+----------------
      sub1                                      | t
      sub2                                      | t
      sub3                                      | t
      pg_16394_sync_16385_7394666715149055164   | t
    (4 rows)
    

すべてのスロットがスタンバイサーバに存在し、上記のSQLクエリの結果(failover_ready)が真である場合、既存のサブスクリプションは、新しいプライマリサーバ上のパブリケーションへのサブスクライブを継続できます。

前述の手続きのうち最初の2つの手順は、PostgreSQLサブスクライバーを対象としています。 これらの手順は、フェイルオーバーの後に指定されたスタンバイに接続する各サブスクライバーノード上で実行することをお勧めします。これにより、レプリケーションスロットの完全なリストを取得できます。 このリストはフェイルオーバーの準備状況の確認のため、手順3で検証されます 一方、非PostgreSQLサブスクライバーは、独自の方法を使用して、それぞれのサブスクリプションで使用されるレプリケーションスロットを識別できます。

計画的なフェイルオーバー中など、場合によっては、PostgreSQLまたは非PostgreSQLのすべてのサブスクライバーが、特定のスタンバイサーバへのフェイルオーバーの後にレプリケーションを継続できることを確認する必要があります。 このような場合は、最初の2つの手順の代わりに以下のSQLを使用して、プライマリ上のどのレプリケーションスロットを昇格対象のスタンバイに同期する必要があるかを特定します。 この問い合わせは、すべてのフェイルオーバーが有効なサブスクリプションに紐づけられた関連するレプリケーションスロットを返します。

/* primary # */ SELECT array_agg(quote_literal(r.slot_name)) AS slots
               FROM pg_replication_slots r
               WHERE r.failover AND NOT r.temporary;
 slots
-------
 {'sub1','sub2','sub3', 'pg_16394_sync_16385_7394666715149055164'}
(1 row)