>> はじめに

本連載をご覧いただいている皆さんであれば、SharePlexが何のソフトかどうかは、既にお分かりかと思います。それは、もちろんOracleのデータをリアルタイムにレプリケーションするソフトです。

では、レプリケーションというデータの複製にとって、一番大切なことはなんでしょうか?

SharePlexの特徴で考えると、様々なOSへの対応や、Oracleのバージョン、そしてエディションへの対応面、前回まで少し特集した高速性、オペレーションに関連する操作性などいろいろと考えられます。

しかし、もっとも重要なことはソース側のデータをターゲット側へと、まったく同じように複製することを保障することが、レプリケーションソフトの使命ではないでしょうか?

今回からは少し、SharePlexがいかにデータの整合性を重要視しているかをご紹介していきます。

>> データが非同期状態になるということ

ソース側とターゲット側で、データが異なる状態、つまり非同期の状態になることが考えれます。その原因には、いくつかのパターンがあります。

  • レプリケーション ソフトウェアの問題
  • ターゲット側でデータを更新
  • ストレージ障害
  • その他

要因はいくつも考えられますが、その中でもターゲット側で間違ってデータを更新してしまった、というようなケースは比較的発生しやすい事象になります。

>> ターゲット側で間違って更新したらどうなるか?

SharePlexをはじめとする論理レプリケーションソフトでは、主にOracleのログを元に、ソースからターゲットへ独立したプロセスで複製を行います。

INSERT、UPDATE、DELETEのDMLのトランザクションを処理していく訳ですが、INSERTは新規でレコードを追加するので、確認は難しいのですが、UPDATEの場合には、元々異なる値があって、それを新規の値に変更するという処理を行います。

その際に、行特定をして、特定の列を単純に変更するという処理も可能ですが、SharePlexの場合には、ソース側のREDOログに記録されたBefore Imageを使用して、元々の値のチェックをして、ターゲット側で値を変更するという動作を行っています。

以下の図を例にしてご説明すると、時間軸を上から下にしてみると、T1からT3までのトランザクションがソース側であり、Balance列だけが変化していきます。その際に、T2からT3の間にターゲット側でBalanceを1500に間違って更新してしまった場合には、エラーが検出されます。これは、ターゲット側のUPDATEをWHERE句を使用して、Balanceが800であったこと確認するためです。

>> 実際に確認してみましょう

では、実際に上図の内容で動作を確認してみます。

テスト用のテーブルの準備

最初にソース側でconfigファイルがdeactivateされた状態を確認しておきます。


sp_ctrl (rhel5sposrc1:2100)> status Brief Status for rhel5sposrc1 Process State PID Running Since --------------- ------------------------------ -------- -------------------- Cop Running 13136 24-Jan-13 16:32:43 Cmd & Ctrl Running 13187 24-Jan-13 16:33:01 There are no active configuration files

configファイルを編集して、定義を追加します。


sp_ctrl (rhel5sposrc1:2100)> edit config ORA_config

expandによって、testユーザスキーマ以下をすべてターゲットへ同名で複製するワイルドカードの設定を追加します。


datasource:o.src1 #source tables target tables routing map splex.demo_src splex.demo_dest rhel5spotrg1@o.trg1 expand test.% test.% rhel5spotrg1@o.trg1

追加した定義内容に基づいてレプリケーションが行われるよう、activateを実行します。


sp_ctrl (rhel5sposrc1:2100)> activate config ORA_config sp_ctrl (rhel5sposrc1:2100)> status Brief Status for rhel5sposrc1 Process State PID Running Since --------------- ------------------------------ -------- -------------------- Cop Running 13136 24-Jan-13 16:32:43 Cmd & Ctrl Running 13187 24-Jan-13 16:33:01 Capture Running 13572 24-Jan-13 16:59:14 Read Running 13573 24-Jan-13 16:59:14 Export Running 13615 24-Jan-13 16:59:18 System is used as a source machine There is 1 active configuration file

expandというワイルドカードの指定がある定義をactivateしたことによって、DDLの伝播も行われるようになったため、testユーザによって、ソース側でテーブルを作成してみます。


[oracle@rhel5sposrc1 ~]$ sqlplus test/test SQL> create table salary ( 2 key char(4), 3 name varchar2(30), 4 balance number(5), 5 primary key(key)); 表が作成されました。

そうするとターゲット側にテーブルが作成されたことが、確認できます。


[oracle@rhel5spotrg1 ~]$ sqlplus test/test SQL> desc salary 名前 NULL? 型 ----------------------------------------- -------- ----------------- KEY NOT NULL CHAR(4) NAME VARCHAR2(30) BALANCE NUMBER(5)

以上で、確認するための準備が整いました。


テスト用のトランザクションを発生させてみる

まずは、ソース側で最初のINSERTを実行します。


SQL> insert into salary values (1234,'hiro',1000); 1行が作成されました。 SQL> commit; コミットが完了しました。

ターゲット側で確認すると、きちんと反映できていることが確認できます。


SQL> select * from salary; KEY NAME BALANCE ---- ------------------------------ ---------- 1234 hiro 1000

次は、例にあったT2のトランザクションです。


SQL> update salary set balance=800 where key=1234; 1行が更新されました。 SQL> commit; コミットが完了しました。

再度ターゲットで確認すると、正常に反映されています。


SQL> select * from salary; KEY NAME BALANCE ---- ------------------------------ ---------- 1234 hiro 800

ターゲット側で間違って値を変更するとどうなるか?

では、例にあったようにターゲット側でbalanceを1500に設定してみます。
ターゲット側もデータベースがオープンな状態で自由に更新が可能ですので、変更ができてしまいます。


SQL> update salary set balance=1500 where key=1234; 1行が更新されました。 SQL> commit; コミットが完了しました。 SQL> select * from salary; KEY NAME BALANCE ---- ------------------------------ ---------- 1234 hiro 1500

その状態で、ソース側を更新してみます。ソース側は当然のことながら、値の更新が可能です。


SQL> update salary set balance=1200 where key=1234; 1行が更新されました。 SQL> commit; コミットが完了しました。 SQL> select * from salary; KEY NAME BALANCE ---- ------------------------------ ---------- 1234 hiro 1200

ターゲットを確認してみると、値が1200にはなっておらず、間違って更新された1500の状態になっています。


SQL> select * from salary; KEY NAME BALANCE ---- ------------------------------ ---------- 1234 hiro 1500

ターゲット側には、sp_ctrlにアクセスしてSharePlexの状態を確認するshow statusdbコマンドで確認するとErrorが発生しています。


sp_ctrl (rhel5spotrg1:2100)> show statusdb Status Database for rhel5spotrg1 Level Details ------- ------------------------------------- Error Table "TEST"."SALARY" out of sync for --------------------------------------------
queue rhel5sposrc1 since 24-Jan-13 17:36:01

Errorが発生してもソース側のDBの更新は止まりませんので、ここで更にbalanceを1200から2000に変更してみましょう。


SQL> update salary set balance=2000 where key=1234; 1行が更新されました。 SQL> commit; コミットが完了しました。 SQL> select * from salary; KEY NAME BALANCE ---- ------------------------------ ---------- 1234 hiro 2000

デフォルトでは、SharePlexは動作を停止させずに、他のレプリケーションを継続します。sp_ctrlからstatusを確認してみても、そのことが確認できます。


sp_ctrl (rhel5spotrg1:2100)> status Brief Status for rhel5spotrg1 Process State PID Running Since --------------- ------------------------------ -------- -------------------- Cop Running 13135 24-Jan-13 16:32:53 Import Running 13483 24-Jan-13 16:59:18 MTPost Running 13484 24-Jan-13 16:59:18 Cmd & Ctrl Running 14079 24-Jan-13 17:45:24 There are no active configuration files

では、非同期状態の内容はどこにあるのでしょうか? 答えは、logディレクトリにあるSID名_errlog.sqlというファイルにあります。


[splex@rhel5spotrg1 ~]$ cd $SP_SYS_VARDIR [splex@rhel5spotrg1 log]$ ls event_log trg1_rhel5sposrc1_opo01.log trg1_errlog.sql trg1_rhel5sposrc1_opo_ddl_01.log

中を確認すると、詳細な非同期状態の情報を確認することが可能です。


[splex@rhel5spotrg1 log]$ cat trg1_errlog.sql -- Host (rhel5sposrc1) Sid (src1) -- session 2, 1 error -- -- -- [1] Thu Jan 24 17:36:01 2013 -- redolog seq#/offset 565/4774416 -- redolog timestamp 805570552 (01/24/13 17:35:52) -- original rowid AAAToeAAEAAAA0jAAA -- Row Not Found-- NOT FOUND update "TEST"."SALARY" t set "BALANCE"='12e2' where rownum = 1 and "BALANCE"='08e2' and "KEY"='1234'; -- ~以下略、発生したerrorの数だけ列記されます~

※BALANCE列の表記はe表記 (指数表記) になっています。

>> まとめ

今回は、errorの確認までを行いましたが、次回は実際に発生した非同期状態を解消していく方法等についてご説明していく予定です。