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

PostgreSQL論理レプリケーションを使用して常に最新の読み取り/書き込みテストサーバーを維持する

    このブログエントリでは、PostgreSQLでの論理レプリケーションについて説明します。そのユースケース、このテクノロジーのステータスに関する一般的な情報、特にプライマリサーバーのサブスクライバー(レプリカ)ノードを順番にセットアップする方法に関する特別なユースケースです。テスト環境のデータベースサーバーとして機能し、課題が解決されました。

    イントロ

    PostgreSQL 10で正式に導入された論理レプリケーションは、PostgreSQLコミュニティが提供する最新のレプリケーションテクノロジーです。論理レプリケーションは、多くのアイデアやコードを共有する物理レプリケーションのレガシーの継続です。論理レプリケーションは、WALを使用した物理レプリケーションのように機能し、バージョンや特定のアーキテクチャに関係なく論理的な変更を記録します。コアオファリングに論理レプリケーションを提供できるようにするために、PostgreSQLコミュニティは長い道のりを歩んできました。

    レプリケーションの種類とPostgreSQLレプリケーションの履歴

    データベース内のレプリケーションのタイプは、次のように分類できます。

    • 物理(別名バイナリ)レプリケーション
      • オペレーティングシステムレベル(vSphereレプリケーション)
      • ファイルシステムレベル(DRBD)
      • データベースレベル(WALベース)
    • 論理レプリケーション(データベースレベル)
      • トリガーベース(DBMirror、Slony)
      • ミドルウェア(pgpool)
      • WALベース(論理的、論理的レプリケーション)

    今日のWALベースの論理レプリケーションを実現するロードマップは次のとおりです。

    • 2001:DBMirror(トリガーベース)
    • 2004:Slony1(トリガーベース)、pgpool(ミドルウェア)
    • 2005:PostgreSQL 8.0で導入されたPITR(WALベース)
    • 2006:PostgreSQL8.2でのウォームスタンバイ
    • 2010:物理ストリーミングレプリケーション、PostgreSQL9.0のホットスタンバイ
    • 2011:PostgreSQL9.1での同期ストリーミングレプリケーション
    • 2012:PostgreSQL9.2でのカスケードストリーミングレプリケーション
    • 2013:PostgreSQL9.3のバックグラウンドワーカー
    • 2014:論理デコードAPI、レプリケーションスロット。 (論理レプリケーションの基盤)PostgreSQL 9.4
    • 2015:2ndQuadrantは、pglogical、祖先、または論理レプリケーションを導入します
    • 2017:コアPostgreSQL 10での論理レプリケーション!

    論理レプリケーションを実現するために多くのテクノロジーが連携していることがわかります。WALアーカイブ、ウォーム/ホットスタンバイ、物理WALレプリケーション、バックグラウンドワーカー、論理デコードです。読者が物理レプリケーションの概念のほとんどに精通していることを前提として、論理レプリケーションの基本コンポーネントについて説明します。

    PostgreSQL論理レプリケーションの基本概念

    いくつかの用語:

    • 出版物: 物理レプリケーションプライマリサーバー上の特定のデータベースで定義された一連のテーブルからの一連の変更。パブリケーションは、INSERT、DELETE、UPDATE、TRUNCATEのすべてまたは一部を処理できます。
    • パブリッシャーノード: パブリケーションが存在するサーバー。
    • レプリカID: UPDATEおよびDELETEのサブスクライバー側の行を識別する方法。
    • サブスクリプション: パブリッシャーノードとその中の1つ以上のパブリケーションへの接続。サブスクリプションは、パブリッシャーの専用レプリケーションスロットをレプリケーションに使用します。追加のレプリケーションスロットは、最初の同期ステップに使用できます。
    • サブスクライバーノード: サブスクリプションが存在するサーバー。

    論理レプリケーションは、パブリッシュ/サブスクライブモデルに従います。 1つ以上のサブスクライバーは、パブリッシャーノード上の1つ以上のパブリケーションをサブスクライブできます。サブスクライバーは、カスケード複製を可能にするために再発行できます。テーブルの論理レプリケーションは、次の2つの段階で構成されます。

    • パブリッシャーでテーブルのスナップショットを取り、サブスクライバーにコピーします
    • (スナップショット以降の)すべての変更を同じ順序で適用する

    論理レプリケーションはトランザクションであり、サブスクライバーに適用される変更の順序がパブリッシャーと同じままであることを保証します。論理レプリケーションは、物理(バイナリ)レプリケーションよりもはるかに自由度が高いため、より多くの方法で使用できます。

    • 単一のデータベースまたはテーブル固有のレプリケーション(クラスター全体をレプリケートする必要はありません)
    • 特定のタスク(GDPRが発効した後の非常にホットなトピックである匿名化など)のトリガーをサブスクライバーに設定する
    • サブスクライバーノードに多くのパブリッシャーノードからデータを収集させることで、中央分析処理が可能になります
    • 異なるバージョン/アーキテクチャ/プラットフォーム間のレプリケーション(ダウンタイムなしのアップグレード)
    • サブスクライバーノードをテスト/開発環境のデータベースサーバーとして使用します。これが必要な理由は、実際のデータに対するテストが最も現実的な種類のテストだからです。

    警告と制限

    論理レプリケーションを使用する際に留意しなければならない特定の事項があります。それらの一部は設計上の決定に影響を与える可能性がありますが、その他は重大なインシデントにつながる可能性があります。

    制限

    • DML操作のみがサポートされています。 DDLはありません。スキーマは事前に定義する必要があります
    • シーケンスは複製されません
    • 大きなオブジェクトは複製されません
    • プレーンベーステーブルのみがサポートされています(マテリアライズドビュー、パーティションルートテーブル、外部テーブルはサポートされていません)

    警告

    遅かれ早かれ論理レプリケーションを使用するときに直面しなければならない基本的な問題は、サブスクライバーでの競合です。サブスクライバーは通常の読み取り/書き込みサーバーであり、物理レプリケーションセットアップでプライマリとして機能することも、カスケード論理レプリケーションセットアップでパブリッシャーとして機能することもできます。サブスクライブされたテーブルへの書き込みが実行されている限り、競合が発生する可能性があります 。レプリケートされたデータが、それらが適用されるテーブルの制約に違反すると、競合が発生します。通常、これを引き起こす操作はINSERT、DELETES、またはUPDATESであり、行が欠落しているために効果がないため、競合は発生しません。競合が発生すると、レプリケーションは停止します。論理バックグラウンドワーカーは指定された間隔(wal_retrieve_retry_interval)で再起動されますが、競合の原因が解決されるまでレプリケーションは再び失敗します。これは、すぐに対処しなければならない重大な状態です。そうしないと、レプリケーションスロットがスタックします 現在の位置で、パブリッシャーノードはWALの蓄積を開始し、必然的にパブリッシャーノードはディスクスペースを使い果たします 。競合は、レプリケーションが停止する可能性がある最も一般的な理由ですが、他の誤った状態でも同じ影響があります。サブスクライブされたテーブルに新しいNOTNULL列を追加したが、デフォルト値を定義するのを忘れた、または公開されたテーブルに列を追加したが、サブスクライブされたテーブルにそれを定義するのを忘れた、またはそのタイプを間違えたが、2つのタイプは互換性。これらのエラーはすべてレプリケーションを停止します。競合を解決するには2つの方法があります:

    1. 実際の問題を解決する
    2. pg_replication_origin_advanceを呼び出して、失敗したトランザクションをスキップします

    解決策b。ここにも示されているように、これは基本的に試行錯誤のプロセスであるため、危険でトリッキーになる可能性があります。パブリッシャーで現在のLSNを選択すると、問題のあるLSN間に操作が行われる可能性があるため、レプリケーションシステムが壊れてしまう可能性があります。保持したい現在のLSN。したがって、最善の方法は、サブスクライバー側で実際に問題を解決することです。例えば。 UNIQUE KEY違反が発生した場合、サブスクライバーのデータを更新するか、行を削除する可能性があります。本番環境では、これらすべてを自動化するか、少なくとも半自動化する必要があります。

    パブリッシャーノードとサブスクライバーノードの設定

    実際の論理レプリケーションの一般的な概要については、このブログをお読みください。

    論理レプリケーションに関連するパラメータは次のとおりです。

    • 発行者側
      • wal_level>="論理的"
      • max_replication_slots> =#subscriptions+初期テーブル同期
      • max_wal_senders> =max_replication_slots + other_physical_standbys
    • サブスクライバー側
      • max_replication_slots> =#subscriptions
      • max_logical_replication_workers> =#subscriptions+初期テーブル同期
      • max_worker_processes> =max_logical_replication_workers + 1 + max_parallel_workers

    論理レプリケーションを実現するために必要な特別な目的から生じる特別な考慮事項に焦点を当てます。テスト部門で使用するテストデータベースクラスターを作成する 。パブリケーションは、すべてのテーブルに対して定義することも、テーブルごとに定義することもできます。最大限の柔軟性が得られるため、テーブルごとのアプローチをお勧めします。一般的な手順は次のように要約できます。

    • サブスクライバノードで新しいinitdbを実行します
    • パブリッシャークラスターのスキーマをダンプし、サブスクライバーノードにコピーします
    • サブスクライバーでスキーマを作成します
    • 必要なテーブルと不要なテーブルを決定します。

    上記の箇条書きに関して、テーブルを複製したり、複製用にセットアップしたりする必要がない理由は2つあります。

    • これは重要性のないダミーテーブルです(おそらく、本番環境からも削除する必要があります)
    • は本番環境にローカルなテーブルです。つまり、テスト(サブスクライバー)環境の同じテーブルに独自のデータがあることは完全に理にかなっています

    論理レプリケーションに参加するすべてのテーブルには、REPLICAIDENTITYが必要です。これはデフォルトでPRIMARYKEYであり、使用できない場合はUNIQUEキーを定義できます。レプリカIDに関するテーブルのステータスを見つけるための次のステップ。

    • REPLICAIDENTITYの明確な候補がないテーブルを検索します
      select table_schema||'.'||table_name from information_schema.tables where table_type='BASE TABLE' AND table_schema||'.'||table_name NOT IN (select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type in ('PRIMARY KEY','UNIQUE')) AND table_schema NOT IN ('information_schema','pg_catalog') ;
    • PRIMARY KEYがなく、UNIQUEINDEXがあるテーブルを検索します
      select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type = 'UNIQUE' EXCEPT select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type = 'PRIMARY KEY';
    • 上記のリストに目を通し、各テーブルをどうするかを決定します
    • PKが存在するテーブルを使用してパブリケーションを作成します
      select 'CREATE PUBLICATION data_for_testdb_pub FOR TABLE ONLY ' || string_agg(qry.tblname,', ONLY ') FROM (select table_schema||'.'||quote_ident(table_name) as tblname from information_schema.tables where table_type='BASE TABLE' AND table_schema||'.'||table_name IN (select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type in ('PRIMARY KEY')) AND table_schema NOT IN( 'information_schema','pg_catalog')  ORDER BY 1) as qry;
      \gexec
    • 次に、サブスクライバーノードでサブスクリプションを作成します
      create subscription data_for_testdb_pub CONNECTION 'dbname=yourdb host=yourdbhost user=repmgr' PUBLICATION data_for_testdb_pub ;
      上記はデータもコピーします。
    • 一意のインデックスを持つ必要なテーブルを追加します
      パブリッシャーノードとサブスクライバーノードの両方で実行します。例:
      ALTER TABLE someschema.yourtable REPLICA IDENTITY USING INDEX yourindex_ukey;
      出版社の場合:
      ALTER PUBLICATION data_for_testdb_pub ADD TABLE ONLY someschema.yourtable;
      サブスクライバーの場合:
      ALTER SUBSCRIPTION data_for_testdb_pub REFRESH PUBLICATION WITH ( COPY_DATA );
    • この時点(同期)では、サブスクライバーノードのPostgreSQLログを常に監視する必要があります。論理レプリケーションの続行を妨げるエラーや何か(タイムアウト)は必要ありません。 エラーをすぐに解決する 、またはパブリッシャーはpg_walにWALファイルを蓄積し続け、最終的にスペースを使い果たします。したがって、
        に対処する必要があります
      • 終了する結果となる論理ワーカーに関するすべてのエラーまたはメッセージ
      • また、
          の世話をします
        • wal_receiver_timeout
        • wal_sender_timeout

    すべての問題を解決したら、サブスクライバーノードを正常に実行する必要があります。したがって、次の質問は、これをテストデータベースサーバーとして使用する方法です。これらの問題/問題に対処する必要があります:

    1. 匿名化
    2. シーケンス違反に基づく主キーと一意キー
    3. 一般的な一連のグッドプラクティス
    4. 監視

    非同化

    EUでGDPRによって実施される個人データの匿名化については、住所、銀行口座、婚姻状況、電話番号、メールアドレスなどに関するすべてのフィールドを空白にするALWAYSトリガーを作成する必要があります。何を保持し、何を空白にするか。論理ワーカーはステートメントをREPLICAとして実行するため、トリガーは常にとして定義する必要があります。

    シーケンス付きの主キー

    シーケンスに関しては、テストを開始する前に処理しない限り、明らかにこれらのキーに問題があります。この場合を考えてみましょう:

    • 金曜日の午後に、サブスクライバデータベースでいくつかのテストを行い、新しい行をテーブルに挿入します。これは、IDとしてシーケンスによって生成された次の値を持ちます。
    • 週末は家に帰ります。
    • 一部の本番ユーザーは、パブリッシャーデータベースの同じテーブルに行を入力します。
    • 行はREPLICAIDENTITYに基づいてサブスクライバーノードに複製されますが、PK違反エラーのために失敗します。論理バックグラウンドワーカーは終了して再試行します。しかし、問題が続く限り失敗し続けます。
    • レプリケーションがスタックします。レプリケーションスロットはWALの蓄積を開始します。
    • パブリッシャーのディスク容量が不足しています。
    • 週末に、プライマリノードがPANICしたというメールが届きます!

    したがって、シーケンスの問題を解決するには、次のアプローチを取ることができます。

    select 'SELECT setval(''' || seqrelid::regclass||''','||CASE WHEN seqincrement <0 THEN -214748364 ELSE 214748364 END||');' from pg_sequence where seqtypid=20;
    \gexec

    上記の機能は、シーケンスを十分に大きな値に設定して、将来かなり大きなウィンドウで重複しないようにすることです。これにより、問題のないテストサーバーを使用できます。

    一連のグッドプラクティス

    あなたは本当にあなたのプログラマーに彼らのテストを非永続的にするように言うべきです。したがって、完了後のテストでは、データベースをテスト前と同じ状態のままにしておく必要があります。シーケンスベースのID挿入では、これは問題ではありません。以前に解決策を見ました。ただし、シーケンス以外の(複合などの)UNIQUEキーでは、問題が発生する可能性があります。したがって、同じ値の本番行がサブスクライブされたテーブルにヒットする前に、これらのテストデータを削除することをお勧めします。

    ここでは、スキーマの変更への対処も追加する必要があります。複製されたDMLトラフィックを中断しないように、すべてのスキーマ変更はサブスクライバーでも実行する必要があります。

    今日のホワイトペーパーをダウンロードするClusterControlを使用したPostgreSQLの管理と自動化PostgreSQLの導入、監視、管理、スケーリングを行うために知っておくべきことについて学ぶホワイトペーパーをダウンロードする

    監視

    あなたは本当に良い監視ソリューションに投資する必要があります。監視する必要があります...

    加入者の場合:

    • 論理ワーカーの終了に関連するサブスクライバーのログ内のすべてのメッセージ。 tail_n_mailとしてツールをインストールすると、これに非常に役立ちます。動作することがわかっている構成:
      INCLUDE: ERROR:  .*publisher.*
      INCLUDE: ERROR:  .*exited with exit.*
      INCLUDE: LOG:  .*exited with exit.*
      INCLUDE: FATAL:  
      INCLUDE: PANIC:
      tail_n_mailからアラートが届いたら、すぐに問題を解決する必要があります。
    • pg_stat_subscription。 Pidはnullであってはなりません。また、ラグは小さくする必要があります。

    出版社で:

    • pg_stat_replication。これには、想定される数の行が含まれている必要があります。接続されているストリーミングレプリケーションスタンバイごとに1つ(サブスクライバノードと他のフィジカルスタンバイが含まれます)。
    • サブスクライバスロットの
    • pg_replication_slots。これはアクティブである必要があります。

    一般に、理想的なテストデータベースサーバーが問題なく実行されるまでには時間がかかりますが、すべてを解決すると、プログラマーはそれを持ってくれてありがとうございます!


    1. リンクサーバーのOLEDBプロバイダーMicrosoft.Jet.OLEDB.4.0のインスタンスを作成できませんnull

    2. MySQLレプリケーションのためのマルチクラウド展開

    3. データの結合と関係の概要

    4. SQL ServerデータベースをMySQLにエクスポートする方法は?