sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLレプリケーションスロットの使用

    レプリケーションスロットとは何ですか?

    「レプリケーションスロット」がまだ導入されていなかった時代には、WALセグメントの管理が課題でした。標準のストリーミングレプリケーションでは、マスターはスレーブのステータスを認識していません。スタンバイノードが数時間メンテナンスモードになっているときに(システムパッケージのアップグレード、ネットワークセキュリティの調整、ハードウェアのアップグレードなど)、大規模なトランザクションを実行するマスターの例を考えてみましょう。ある時点で、マスターはチェックポイントが通過するときにトランザクションログ(WALセグメント)を削除します。スレーブがメンテナンスから外れると、スレーブのラグが大きくなり、マスターに追いつく必要があります。最終的に、スレーブは以下のような致命的な問題を抱えることになります:

    LOG:  started streaming WAL from primary at 0/73000000 on timeline 1
    
    FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000000000073 has already been removed

    一般的なアプローチは、postgresql.confで、WALファイルを1つ以上の長期アーカイブの場所にコピーするWALアーカイブスクリプトを指定することです。スタンバイやその他のストリーミングレプリケーションクライアントがない場合、基本的に、アーカイブスクリプトが完了するか、OKと応答すると、サーバーはWALファイルを破棄できます。ただし、クラッシュリカバリにはまだいくつかの最近のWALファイルが必要です(最近のWALファイルのデータはクラッシュリカバリ中に再生されます。長いメンテナンス期間に配置されたスタンバイノードの例では、オンラインに戻って要求するときに問題が発生しますプライマリに存在しなくなったWALファイルのプライマリの場合、レプリケーションは失敗します。

    この問題は、PostgreSQL9.4で「レプリケーションスロット」を介して解決されました。

    レプリケーションスロットを使用しない場合、レプリケーションが失敗するリスクを減らす一般的な方法は、必要になる可能性のあるWALファイルがローテーションまたはリサイクルされないようにwal_keep_segmentsを十分に高く設定することです。このアプローチの欠点は、セットアップに最適な値を判断するのが難しいことです。毎日のメンテナンスは必要ありません。また、ディスクストレージを消費する大量のWALファイルを保持する必要もありません。これは機能しますが、マスターのディスクスペースを危険にさらすと、着信トランザクションが失敗する可能性があるため、理想的なソリューションではありません。

    レプリケーションスロットを使用しない別のアプローチは、継続的なアーカイブを使用してPostgreSQLを構成し、restore_commandを提供してレプリカにアーカイブへのアクセスを許可することです。プライマリでのWALの蓄積を回避するために、WALファイル用に別のボリュームまたはストレージデバイス(SANやNFSなど)を使用できます。もう1つは、プライマリがスタンバイノードがトランザクションをコミットするのを待機する必要があるため、同期レプリケーションの場合です。これは、WALファイルがスタンバイノードに適用されていることを保証します。ただし、それでも、プライマリからアーカイブコマンドを提供して、WALがプライマリでリサイクルされたら、回復のためにWALバックアップがあるので安心することをお勧めします。状況によっては、同期レプリケーションは、非同期レプリケーションと比較してパフォーマンスのオーバーヘッドが発生するため、理想的なソリューションではありません。

    レプリケーションスロットの種類

    レプリケーションスロットには、2つのタイプがあります。これらは次のとおりです。

    物理レプリケーションスロット 標準のストリーミングレプリケーションに使用できます。彼らは、データが早すぎてリサイクルされないようにします。

    論理レプリケーションスロット

    論理レプリケーションは、物理レプリケーションスロットと同じことを行い、論理レプリケーションに使用されます。ただし、これらは論理デコードに使用されます。論理デコードの背後にある考え方は、ユーザーがトランザクションログに添付し、プラグインを使用してデコードする機会を与えることです。これにより、データベースに加えられた変更、したがってトランザクションログに加えられた変更を任意の形式および目的で抽出できます。

    このブログでは、物理レプリケーションスロットを使用し、ClusterControlを使用してこれを実現する方法を説明します。

    レプリケーションスロットを使用することの長所と短所

    レプリケーションスロットは、一度有効にすると間違いなく有益です。デフォルトでは、「レプリケーションスロット」は有効になっていないため、手動で設定する必要があります。レプリケーションスロットを使用する利点には、次のようなものがあります

      マスターがすべてのレプリカがそれらを受信するのに十分なWALセグメントを保持することを保証します マスターがレプリカでリカバリの競合を引き起こす可能性のある行を削除しないようにします
    • マスターは、トランザクションログがすべてのレプリカによって消費された場合にのみ、トランザクションログをリサイクルできます。ここでの利点は、スレーブがそれほど遅れることがなく、再同期が必要になることはないということです。
    レプリケーションスロットにもいくつかの注意事項があります。

    • 孤立したレプリケーションスロットは、マスターからのWALファイルの積み重ねにより、無制限のディスク成長を引き起こす可能性があります
    • 長期間(数日や数週間など)のメンテナンスが行われ、レプリケーションスロットに関連付けられているスレーブノードでは、マスターからのWALファイルが積み重なるため、ディスクが無制限に増加します。

    これを監視するには、pg_replication_slotsにクエリを実行して、使用されていないスロットを特定します。これについては後でもう一度確認します。

    レプリケーションスロットの使用

    前述のように、レプリケーションスロットには2つのタイプがあります。このブログでは、ストリーミングレプリケーションに物理レプリケーションスロットを使用します。

    レプリケーションスロットの作成 レプリケーションの作成は簡単です。これを行うには、既存の関数pg_create_physical_replication_slotを呼び出す必要があり、マスターノードで実行および作成する必要があります。機能はシンプルです

    maximus_db=# \df pg_create_physical_replication_slot
    
    Schema              | pg_catalog
    
    Name                | pg_create_physical_replication_slot
    
    Result data type    | record
    
    Argument data types | slot_name name, immediately_reserve boolean DEFAULT false, OUT slot_name name, OUT xlog_position pg_lsn
    
    Type                | normal

    例: slot1という名前のレプリケーションスロットを作成します

    postgres=# SELECT pg_create_physical_replication_slot('slot1');
    
    -[ RECORD 1 ]-----------------------+---------
    
    pg_create_physical_replication_slot | (slot1,)

    レプリケーションスロット名とその基礎となる構成は、システム全体のみであり、クラスター全体ではありません。たとえば、nodeA(現在のマスター)とスタンバイノードnodeBおよびnodeCがあり、マスターnodeA、つまり「slot1」にスロットを作成している場合、データはnodeBおよびnodeCで使用できません。したがって、フェイルオーバー/スイッチオーバーが発生しようとしているときは、作成したスロットを再作成する必要があります。

    レプリケーションスロットの削除 未使用のレプリケーションスロットを削除または削除する必要があります。前述のように、孤立したレプリケーションスロット、またはクライアントノードやスタンバイノードに割り当てられていないスロットがある場合、ドロップしないままにしておくと、無限のディスクスペースの問題が発生する可能性があります。したがって、使用しなくなったときにこれらを削除する必要があることが非常に重要です。ドロップするには、pg_drop_replication_slotを呼び出すだけです。この関数の定義は次のとおりです。

    maximus_db=# \df pg_drop_replication_slot
    
    Schema              | pg_catalog
    
    Name                | pg_drop_replication_slot
    
    Result data type    | void
    
    Argument data types | name
    
    Type                | normal

    ドロップするのは簡単です:

    maximus_db=# select pg_drop_replication_slot('slot2');
    
    -[ RECORD 1 ]------------+-
    
    pg_drop_replication_slot |

    PostgreSQLレプリケーションスロットの監視

    レプリケーションスロットの監視は、見逃したくないものです。以下のように、プライマリ/マスターノードのビューpg_replication_slotsから情報を収集するだけです。

    postgres=# select * from pg_replication_slots;
    
    -[ RECORD 1 ]-------+-----------
    
    slot_name           | main_slot
    
    plugin              |
    
    slot_type           | physical
    
    datoid              |
    
    database            |
    
    active              | t
    
    active_pid          | 16297
    
    xmin                |
    
    catalog_xmin        |
    
    restart_lsn         | 2/F4000108
    
    confirmed_flush_lsn |
    
    -[ RECORD 2 ]-------+-----------
    
    slot_name           | main_slot2
    
    plugin              |
    
    slot_type           | physical
    
    datoid              |
    
    database            |
    
    active              | f
    
    active_pid          |
    
    xmin                |
    
    catalog_xmin        |
    
    restart_lsn         |
    
    confirmed_flush_lsn |

    上記の結果は、main_slotが取得されたことを示していますが、main_slot2は取得されていません。

    あなたができるもう一つのことは、あなたが持っているスロットからどれだけ遅れているかを監視することです。これを実現するには、以下のサンプル結果に基づくクエリを使用するだけです。

    postgres=# SELECT redo_lsn, slot_name,restart_lsn, 
    
    round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind 
    
    FROM pg_control_checkpoint(), pg_replication_slots;
    
    redo_lsn    | slot_name | restart_lsn | gb_behind 
    
    ------------+-----------+-------------+-----------
    
     1/8D400238 |     slot1 | 0/9A000000 | 3.80

    ただし、redo_lsnは9.6には存在しないため、redo_locationを使用する必要があるため、9.6では

    imbd=# SELECT redo_location, slot_name,restart_lsn, 
    
    round((redo_location-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind 
    
    FROM pg_control_checkpoint(), pg_replication_slots;
    
    -[ RECORD 1 ]-+-----------
    
    redo_location | 2/F6008BE0
    
    slot_name     | main_slot
    
    restart_lsn   | 2/F6008CC0
    
    gb_behind     | 0.00
    
    -[ RECORD 2 ]-+-----------
    
    redo_location | 2/F6008BE0
    
    slot_name     | main_slot2
    
    restart_lsn   | 2/F6008CC0
    
    gb_behind     | 0.00
    システム変数の要件

    レプリケーションスロットを実装するには、手動で設定する必要があります。変更が必要で、postgresql.confで指定する必要がある変数があります。以下を参照してください:

    • max_replication_slots – 0に設定されている場合、これはレプリケーションスロットが完全に無効になっていることを意味します。 PostgreSQL <10バージョンを使用している場合、このスロットは0(デフォルト)以外に指定する必要があります。 PostgreSQL 10以降、デフォルトは10です。この変数はレプリケーションスロットの最大数を指定します。現在存在するレプリケーションスロットの数よりも低い値に設定すると、サーバーを起動できなくなります。
    • wal_level –少なくともレプリカ以上である必要があります(レプリカがデフォルトです)。 hot_standbyまたはarchiveを設定すると、レプリカにマップされます。物理レプリケーションスロットの場合、レプリカで十分です。論理レプリケーションスロットの場合、論理が優先されます。
    • max_wal_senders –デフォルトで10に設定されています。9.6バージョンでは0に設定されています。これは、レプリケーションが無効になっていることを意味します。特にClusterControlで実行する場合は、これを少なくとも16に設定することをお勧めします。
    • hot_standby –バージョン<10では、これをデフォルトでオフに設定する必要があります。これはスタンバイノードにとって重要です。つまり、オンの場合、リカバリ中またはスタンバイモードで接続してクエリを実行できます。
    • primary_slot_name –この変数は、スタンバイノードのrecovery.confを介して設定されます。これは、送信者(またはプライマリ/マスター)と接続するときに受信者またはスタンバイノードが使用するスロットです。

    これらの変数は、ほとんどの場合、新しい値を再ロードするためにデータベースサービスを再起動する必要があることに注意する必要があります。

    ClusterControlPostgreSQL環境でのレプリケーションスロットの使用

    では、物理レプリケーションスロットを使用して、ClusterControlによって管理されるPostgresセットアップ内に実装する方法を見てみましょう。

    PostgreSQLデータベースノードの導入

    今回は、PostgreSQL9.6バージョンを使用したClusterControlを使用した3ノードのPostgreSQLクラスターのデプロイを開始しましょう。

    ClusterControlは、デフォルトに基づいて定義された次のシステム変数を使用してノードをデプロイしますまたは調整された値。で:

    postgres=# select name, setting from pg_settings where name in ('max_replication_slots', 'wal_level', 'max_wal_senders', 'hot_standby');
    
             name          | setting 
    
    -----------------------+---------
    
     hot_standby           | on
    
     max_replication_slots | 0
    
     max_wal_senders       | 16
    
     wal_level             | replica
    
    (4 rows)
    バージョンPostgreSQL>9.6では、max_replication_slotsのデフォルト値はデフォルトで有効になっている10ですが、デフォルトで無効になっている9.6以下のバージョンでは無効です。 max_replication_slotsを0より大きく割り当てる必要があります。この例では、max_replication_slotsを5に設定します。

    [email protected]:~# grep 'max_replication_slots' /etc/postgresql/9.6/main/postgresql.conf 
    
    # max_replication_slots = 0                     # max number of replication slots
    
    max_replication_slots = 5
    そしてサービスを再開しました

    [email protected]:~# pg_lsclusters 
    
    Ver Cluster Port Status Owner    Data directory Log file
    
    9.6 main    5432 online postgres /var/lib/postgresql/9.6/main pg_log/postgresql-%Y-%m-%d_%H%M%S.log
    
    
    
    [email protected]:~# pg_ctlcluster 9.6 main restart
    プライマリノードとスタンバイノードのレプリケーションスロットの設定

    ClusterControlにはこれを行うオプションがないため、スロットを手動で作成する必要があります。この例では、ホスト192.168.30.100のプライマリにスロットを作成しました:

    192.168.10.100:5432 [email protected]_db=# SELECT pg_create_physical_replication_slot('slot1'), pg_create_physical_replication_slot('slot2');
    
     pg_create_physical_replication_slot | pg_create_physical_replication_slot 
    
    -------------------------------------+-------------------------------------
    
     (slot1,)                            | (slot2,)
    
    (1 row)
    作成したばかりの番組を確認する

    192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
    
     slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn 
    
    -----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
    
     slot1     | | physical  | | | f      | | |       | | 
    
     slot2     | | physical  | | | f      | | |       | | 
    
    (2 rows)

    スタンバイノードで、recovery.confを更新し、変数primary_slot_nameを追加し、application_nameを変更して、ノードを識別しやすくする必要があります。ホスト192.168.30.110のrecovery.confでは次のようになります。

    [email protected]:/var/lib/postgresql/9.6/main/pg_log# cat ../recovery.conf 
    
    standby_mode = 'on'
    
    primary_conninfo = 'application_name=node11 host=192.168.30.100 port=5432 user=cmon_replication password=m8rLmZxyn23Lc2Rk'
    
    recovery_target_timeline = 'latest'
    
    primary_slot_name = 'slot1'
    
    trigger_file = '/tmp/failover_5432.trigger'

    ホスト192.168.30.120でも同じことを行いますが、application_nameを変更し、primary_slot_name='slot2'を設定します。

    レプリケーションスロットの状態を確認する:

    192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
    
     slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn 
    
    -----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
    
     slot1     | | physical  | | | t      | 24252 | |       | 0/CF0A4218 | 
    
     slot2     | | physical  | | | t      | 11635 | |       | 0/CF0A4218 | 
    
    (2 rows)

    他に何が必要ですか?

    現時点では、ClusterControlはレプリケーションスロットをサポートしていないため、考慮する必要があることがあります。これは何?詳細を見てみましょう。

    フェイルオーバー/スイッチオーバープロセス

    ClusterControlを介した自動フェイルオーバーまたはスイッチオーバーが試行された場合、スロットはプライマリノードおよびスタンバイノードから保持されません。これを手動で再作成し、変数が正しく設定されているかどうかを確認し、それに応じてrecovery.confを変更する必要があります。

    マスターからのスレーブの再構築

    スレーブを再構築する場合、recovery.confは保持されません。これは、primary_slot_nameを持つrecovery.conf設定が消去されることを意味します。これを再度手動で指定し、pg_replication_slotsビューをチェックして、スロットが適切に使用されているか、孤立したままになっているかを判断する必要があります。

    マスターからスレーブ/スタンバイノードを再構築する場合は、以下のコマンドのようにPGAPPNAMEenv変数を指定することを検討する必要がある場合があります。

    $ export PGAPPNAME="app_repl_testnode15"; /usr/pgsql-9.6/bin/pg_basebackup -h 192.168.10.190 -U cmon_replication -D /var/lib/pgsql/9.6/data -p5434 -W -S main_slot -X s -R -P

    -R paramを指定することは非常に重要であるため、recovery.confが再作成されます。一方、-Sは、スタンバイノードを再構築するときに使用するスロット名を指定します。

    結論

    PostgreSQLでのレプリケーションスロットの実装は簡単ですが、覚えておく必要のある特定の注意事項があります。 ClusterControlを使用してデプロイする場合、フェイルオーバーまたはスレーブの再構築中にいくつかの設定を更新する必要があります。


    1. MySQL LEAST()関数–引数のリストから最小の引数を検索します

    2. SQLであるテーブルから別のテーブルにデータをコピーする方法

    3. PostgreSQLデータベースを復元する際の特権の問題を解決する方法

    4. T-SQLを使用してリンクサーバーオプションを編集する方法