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

PostgreSQLメジャーバージョン8.4.x/9.3.xのアップグレード中のSlony-Iでのスイッチオーバー/スイッチバック

    PostgreSQLのすべての新しいリリースには、エキサイティングな機能が満載されています。新機能を利用するには、データベースサーバーをアップグレードする必要があります。 pg_dump / pg_restoreやpg_upgradeなどの従来のアップグレードパスを選択すると、アプリケーションの大幅なダウンタイムが必要になります。現在、完全なロールバック計画を備えた主要なPostgreSQLバージョン間で最小のダウンタイムアップグレードパスを探している場合、それは非同期Slony-Iレプリケーションによって実現されます。 Slony-I(詳細はこちら)には、異なるPostgreSQLバージョン、OS、ビットアーキテクチャ間で簡単に複製できる機能があるため、大幅なダウンタイムを必要とせずにアップグレードを実行できます。さらに、その設計には一貫したスイッチオーバーおよびスイッチバック機能があります。

    IMOは、メジャーバージョンのアップグレードを行っている間、適切なフォールバックプランを立てる必要があります。これは、アプリケーションにバグがあったり、アップグレードされたバージョンでパフォーマンスが低下した場合に備えて、すぐに古いバージョンにロールバックできるようにするためです。 Slony-Iは、スイッチバックの方法でそのような機能を提供します。この投稿は、スイッチオーバー/スイッチバック手順を含む最小限のダウンタイムアップグレードを示しています。

    デモに進む前に、注意すべき重要なステップの1つは、PG 9.0.xバージョンのbyteaデータ型列では、データをESCAPE形式で保存し、後のバージョンではHEX形式で保存するために使用します。スイッチバック(新しいバージョンから古いバージョンへ)を実行している間、この種のbytea形式の違いはSlony-Iでサポートされていないため、アップグレード期間中はESCAPE形式を維持する必要があります。そうしないと、エラーが発生する可能性があります。

    ERROR  remoteWorkerThread_1_1: error at end of COPY IN: ERROR:  invalid input syntax for type bytea
    CONTEXT: COPY sl_log_1, line 1: "1 991380 1 100001 public foo I 0 {id,500003,name,"A ",b,"\\x41"}"
    ERROR remoteWorkerThread_1: SYNC aborted

    修正するには、PG 8.4.xでは変更は必要ありませんが、PG 9.3.5では、図のようにbytea_outputパラメーターをHEXからESCAPEに設定する必要があります。クラスタレベル($ PGDATA / postgresql.conf)またはユーザーレベル(ALTER TABLE…SET)で設定できます。ユーザーレベルの変更を使用することをお勧めします。

    slavedb=# alter user postgres set bytea_output to escape;
    ALTER ROLE

    アップグレード手順を進めましょう。以下は、このデモで使用した2つのバージョンのサーバーの詳細です。試行している場合は、サーバーの設定に従って変更してください。

    Origin Node (Master/Primary are called as Origin)                     Subscriber Node (Slave/Secondary are called as Subscriber)
    ------------------------------------------------- ----------------------------------------------------------
    Host IP : 192.168.22.130 192.168.22.131
    OS Version : RHEL 6.5 64 bit RHEL 6.5 64 bit
    PG Version : 8.4.22 (5432 Port) 9.3.5 (5432 Port)
    Slony Vers. : 2.2.2 2.2.2
    PG Binaries : /usr/local/pg84/bin /opt/PostgreSQL/9.3/
    Database : masterdb slavedb
    PK Table : foo(id int primary key, name char(20), image bytea) ...restore PK tables structure from Origin...

    わかりやすく実装しやすいように、デモを3つのセクションに分けました

    1.PostgreSQLバージョンに対するSlony-Iバイナリのコンパイル
    2。レプリケーションスクリプトの作成と実行
    3。スイッチオーバー/スイッチバックのテスト。

    1。 PostgreSQLバージョンに対するSlony-Iバイナリのコンパイル
    ここからSlony-Iソースをダウンロードし、オリジンノードとサブスクライバーノードのPostgreSQLバイナリに対してソースインストールを実行します。

    On Origin Node:
    # tar -xvf slony1-2.2.2.tar.bz2
    # cd slony1-2.2.2
    ./configure --with-pgbindir=/usr/local/pg84/bin
    --with-pglibdir=/usr/local/pg84/lib
    --with-pgincludedir=/usr/local/pg84/include
    --with-pgpkglibdir=/usr/local/pg84/lib/postgresql
    --with-pgincludeserverdir=/usr/local/pg84/include/postgresql/
    make
    make install

    On Subscriber Node: (assuming PG 9.3.5 installed)
    # tar -xvf slony1-2.2.2.tar.bz2
    # cd slony1-2.2.2
    ./configure --with-pgconfigdir=/opt/PostgreSQL/9.3/bin
    --with-pgbindir=/opt/PostgreSQL/9.3/bin
    --with-pglibdir=/opt/PostgreSQL/9.3/lib
    --with-pgincludedir=/opt/PostgreSQL/9.3/include
    --with-pgpkglibdir=/opt/PostgreSQL/9.3/lib/postgresql
    --with-pgincludeserverdir=/opt/PostgreSQL/9.3/include/postgresql/server/
    --with-pgsharedir=/opt/PostgreSQL/9.3/share
    make
    make install

    2。レプリケーションスクリプトの作成と実行
    レプリケーションを設定するには、スイッチオーバー/スイッチバックなど、レプリケーションを処理するスクリプトをいくつか作成する必要があります。

    1. initialize.slonik –このスクリプトは、オリジン/サブスクライバーノードの接続情報を保持します。
    2。 create_set.slonik –このスクリプトは、サブスクライバーノードに複製されるすべてのOriginPKテーブルを保持します。
    3。 subscribe_set.slonik –このスクリプトは、セットデータのサブスクライバーノードへの複製を開始します。
    4。 switchover.slonik –このスクリプトは、コントロールをOriginからSubscriberに移動するのに役立ちます。
    5。 switchback.slonik –このスクリプトは、サブスクライバーからオリジンへのフォールバック制御に役立ちます。

    最後に、さらに2つの起動スクリプト“ start_OriginNode.sh” および「start_SubscriberNode.sh」 これは、オリジン/サブスクライバーノードでコンパイルされたバイナリに従ってslonプロセスを開始します。

    ここからすべてのスクリプトをダウンロードします。

    これは、FooテーブルのOriginノード(8.4.22)のサンプルデータで、byteaデータ型の列があり、作成されたスクリプトを使用してサブスクライバーノード(9.3.5)に複製します。

    masterdb=# select * from foo;
    id | name | image
    ----+----------------------+-------
    1 | Raghav | test1
    2 | Rao | test2
    3 | Rags | test3
    (3 rows)

    スクリプトを1つずつ呼び出して、レプリケーションを設定しましょう。すべてのSLONIKスクリプトは、個別に実行する必要がある「start_OriginNode.sh」と「start_SubscriberNode.sh」を除いて、ORIGINノードでのみ実行する必要があることに注意してください。

    -bash-4.1$ slonik initalize.slonik
    -bash-4.1$ slonik create_set.slonik
    create_set.slonik:13: Set 1 ...created
    create_set.slonik:16: PKey table *** public.foo *** added.
    -bash-4.1$ sh start_OriginNode.sh
    -bash-4.1$ sh start_SubscriberNode.sh //ON SUBSCRIBER NODE
    -bash-4.1$ slonik subscribe_set.slonik

    上記のスクリプトが正常に実行されると、Origin(masterdb)のデータがSubscriber(slavedb)に複製されていることがわかります。また、サブスクライバーノードでのDML操作を許可しません:

    slavedb=# select * from foo;
    id | name | image
    ----+----------------------+-------
    1 | Raghav | test1
    2 | Rao | test2
    3 | Rags | test3
    (3 rows)

    slavedb=# insert into foo values (4,'PG-Experts','Image2');
    ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

    かっこいい…データを新しいバージョンのPostgreSQL9.3.5に移動しました。この段階で、すべてのデータがサブスクライバーノードに複製されたと思われる場合は、切り替えを行うことができます。

    3。スイッチオーバー/スイッチバックのテスト。

    スクリプトを使用して最新バージョンに切り替えて、サブスクライバー/オリジンノードにデータを挿入してみましょう。

    -bash-4.1$ slonik switchover.slonik
    switchover.slonik:8: Set 1 has been moved from Node 1 to Node 2

    slavedb=# insert into foo values (4,'PG-Experts','Image2');
    INSERT 0 1

    masterdb=# select * from foo ;
    id | name | image
    ----+----------------------+-------
    1 | Raghav | test1
    2 | Rao | test2
    3 | Rags | test3
    4 | PG-Experts | Image2
    (4 rows)

    masterdb=# insert into foo values (5,'PG-Experts','Image3');
    ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

    完璧…これが私たちが探しているものです。現在、PG 9.3.5バージョンを実行しているslavedb(サブスクライバーノード)がデータを受け入れ、masterdb(オリジンノード)がslavedbデータを受け取ります。また、masterdbで実行されたDMLを拒否します。

    Slony-I Logsは、スイッチオーバー時のオリジン/サブスクライバーノードIDの動きを示します:

    2014-12-12 04:55:06 PST CONFIG moveSet: set_id=1 old_origin=1 new_origin=2
    2014-12-12 04:55:06 PST CONFIG storeListen: li_origin=1 li_receiver=2 li_provider=1
    2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: update provider configuration
    2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: helper thread for provider 1 terminated
    2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: disconnecting from data provider 1
    ...
    ...
    2014-12-12 04:55:11 PST INFO start processing ACCEPT_SET
    2014-12-12 04:55:11 PST INFO ACCEPT: set=1
    2014-12-12 04:55:11 PST INFO ACCEPT: old origin=1
    2014-12-12 04:55:11 PST INFO ACCEPT: new origin=2
    2014-12-12 04:55:11 PST INFO ACCEPT: move set seq=5000006393
    2014-12-12 04:55:11 PST INFO got parms ACCEPT_SET

    この段階で問題が発生した場合は、古いバージョンに戻すことができます。スイッチバック後、アプリケーションまたはその他の問題が修正されるまで、古いバージョンを続行できます。これは、切り替え後に問題が発生した場合に多くの時間を無駄にすることなく、完璧なロールバックプランです。

    -bash-4.1$ slonik switchback.slonik
    switchback.slonik:8: Set 1 has been moved from Node 2 to Node 1

    slavedb=# insert into foo values (5,'PG-Experts','Image3');
    ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

    masterdb=# insert into foo values (5,'PG-Experts','Image3');
    INSERT 0 1

    slavedb=# select * from foo ;
    id | name | image
    ----+----------------------+-------
    1 | Raghav | test1
    2 | Rao | test2
    3 | Rags | test3
    4 | PG-Experts | Image2
    5 | PG-Experts | Image3
    (5 rows)

    非常に素晴らしい…!!!これは、ダウンタイムを最小限に抑えた正確なロールバックではありませんか?はい、トランザクションを逃すことなくノードを完全に切り替えることができます。

    サブスクライバーからオリジンノードへのスイッチバックを示すログ:

    2014-12-12 04:58:45 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1
    2014-12-12 04:58:45 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
    2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: update provider configuration
    2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: helper thread for provider 2 terminated
    2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: disconnecting from data provider 2
    2014-12-12 04:58:46 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
    ...
    ...
    2014-12-12 04:58:47 PST INFO start processing ACCEPT_SET
    2014-12-12 04:58:47 PST INFO ACCEPT: set=1
    2014-12-12 04:58:47 PST INFO ACCEPT: old origin=2
    2014-12-12 04:58:47 PST INFO ACCEPT: new origin=1
    2014-12-12 04:58:47 PST INFO ACCEPT: move set seq=5000006403
    2014-12-12 04:58:47 PST INFO got parms ACCEPT_SET
    2014-12-12 04:58:48 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1

    お気づきかもしれませんが、PostgreSQLバージョン間の切り替え操作中にトランザクションが失われることはありません。アプリケーションがオリジンノードとサブスクライバーノードに接続するために開始/停止するのはダウンタイムだけかもしれませんが、オリジン/サブスクライバーノードがダウンすることはありませんが、稼働しているだけです。

    ここに示されている方法は、アップグレードに役立つだけでなく、ノード間を移動するためのSlony-Iの同じ方法であることを忘れないでください。

    お待ちいただいてありがとうございます :)。この投稿が、適切なロールバック計画を含むSlony-Iを使用して、ダウンタイムを最小限に抑えてPostgreSQLをアップグレードするのに役立つことを願っています。


    1. MSSQLのトランザクション分離レベルに応じた読み取り/書き込みロックのヒント

    2. SQLサーバースキーマとデフォルトスキーマ

    3. CodeIgniter:提供された設定を使用してデータベースサーバーに接続できませんエラーメッセージ

    4. 致命的なエラー:キャッチされない例外'mysqli_sql_exception'とメッセージ'クエリ/プリペアドステートメントでインデックスが使用されていません'