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

SlonyスレーブノードでDELETE/UPDATEではなくINSERTのみを複製する方法は?

    そもそも、なぜそのような要件が必要なのかを知る必要があります。 IMO、ターゲットデータベース(スレーブノード)にある種の履歴データを維持することは絶対にビジネス上の必要性です。特に、複数のスレーブノードのうちの1つは、データベースに最初に書き込まれたときにデータの最初の形式を保持します。

    この要件を達成するには、スレーブノードでTRIGGER / RULEのようなある種のフィルターを考え出し、DELETEステートメントとUPDATEステートメントのリレーを回避する必要があります。 Slony-Iを扱っているため、マスターノードからすべてのイベントを収集しますが、スレーブノードでDMLを再生しながらDMLをフィルタリングするような組み込みのメカニズムはありません(AFAIK Mysql、Oracle、SQLServerはフィルターをサポートしています) 。

    これをまっすぐにするために、従来のSlony-Iの方法では、すべてのノードにわたって行の一意性を維持し、テーブルのコアコンセプトには主キーが必要です。このようなアーキテクチャ設計では、DELETE / UPDATEステートメントを除外するのは困難です。たとえば、「orders」テーブルの主キー列「orderid」には、値100の最初のINSERTステートメントがあり、フィルター処理されたスレーブノードに最初のフォームとして複製されます。その後、DELETEステートメントが「orderid =100」に対して実行され、行が削除されました。INSERTまたはUPDATEステートメントが「orderid =100」を使用しようとすると、スレーブノードが重複キー違反でヒットし、単純にレプリケーションが中断されます。

    ERROR:  duplicate key value violates unique constraint "reptest_pkey"
    DETAIL: Key (id)=(2) already exists.
    CONTEXT: SQL statement "INSERT INTO "public"."reptest" ("id", "name") VALUES ($1, $2);"
    .....
    or
    ....
    CONTEXT: SQL statement "UPDATE ONLY "public"."reptest" SET "id" = $1 WHERE "id" = $2;"
    2014-11-17 23:18:53 PST ERROR remoteWorkerThread_1: SYNC aborted

    したがって、ルールの実装はまだ問題ではありませんが、ルールを適用する場合は非常に注意する必要があります。ただし、実際には、これらのフィルターをSlony-Iスレーブノードに適用することは非常に脆弱です。特に、アプリケーション/開発者は、INSERTまたはUPDATEによる行の重複エントリがレプリケーションを中断する可能性があることを常に念頭に置いておく必要があります。

    Slony-IだけではDMLルールを使用できないため、PostgreSQLCREATERULE…ONDELETE/ON UPDATE DO INSTEAD NOTHINGを使用し、ALTERTABLE…ENABLEREPLICARULEを使用してそのルールをテーブルに適用してDELETE/UPDATEステートメントを無効にすることができます。このオプションを使用するには多くの規律が必要であるため、アプリケーションとスタッフがこれらのルールに実際に従うようにすることができます。

    手順を続行するには、スロニーセットアップが必要です。セットアップが必要になる可能性が低い場合は、ここで私の過去の投稿を参照できます。

    スレーブノードの手順(マスターDB:postgres、スレーブDB:デモ、ポート:5432):

    1.slonデーモンを停止します
    2。 ONDELETEおよびONUPDATEDOINSTEADNOTHINGルールを作成します

    demo=# CREATE RULE void_delete AS ON DELETE TO reptest DO INSTEAD NOTHING;
    CREATE RULE
    demo=# CREATE RULE void_update AS ON UPDATE TO reptest DO INSTEAD NOTHING;
    CREATE RULE

    3.テーブルにルールを適用します

    demo=# ALTER TABLE reptest ENABLE REPLICA RULE void_delete;
    ALTER TABLE
    demo=# ALTER TABLE reptest ENABLE REPLICA RULE void_update ;
    ALTER TABLE

    4.Slonデーモンを起動します

    これで、UPDATE/DELETEがスレーブノードに影響を与えないことがわかります。

    postgres=# delete from reptest where id =2;
    DELETE 1
    postgres=# update reptest set id=2 where id=1;
    UPDATE 1

    --On Master
    postgres=# select * from reptest ;
    id | name
    ----+------------
    2 | A
    (1 row)

    --On Slave
    demo=# select * from reptest ;
    id | name
    ----+------------
    1 | A
    2 | C
    (2 rows)

    INSERTステートメントが値1で実行された場合、レプリケーションが中断されます。注意してください…!!

    dblinksのようなこのリクエストを完全に満たす他の方法、BEFORE DELETEのようなトリガー…関数からNULL値を返すことを忘れないでください。しかし、Slonyレプリケーションで作業している場合、最も効率的な方法はRULE / ENABLEREPLICARULEを使用することだと思います。

    これまでに、PostgreSQL 9.4の論理デコードレプリケーションスロットの新機能に関する多くのブログを読んだことがあるかもしれません。将来的には、スレーブ上のフィルターDMLの概念が含まれることを期待しています。

    ご覧いただきありがとうございます。


    1. CodeigniterでのWHERE句のグループ化

    2. 収集方法:OracleデータベースのDELETEプロシージャ

    3. すべてのテーブルのシーケンスIDpostgreSQLを一括更新する方法

    4. pl\sqlを使用してclobを1行ずつ読み取る