この記事ではリリースノートにおいて SharePlexでサポートしない旨の記述がなされている'UPDATE WITH CASE'構文により変更される行 について説明します。
* SharePlex does not support the following for any table type
- Replication of rows changed by 'UPDATE WITH CASE' syntax.
以下の例のように既存の2つの行の間でユニークキーの列の値を交換するするようにCASEステートメントを伴うソース側テーブルを更新する場合、ターゲットでは一意制約違反により非同期になります。
ソースでは一つのUpdateで両方の行を更新するため一意制約違反は起きません。ターゲットでは SharePlex PostプロセスはRedoログに書かれている内容に基づいて各行へのUpdateステートメントを実行します。そのため、一意制約違反が生じます。
例
次のように定義されたテーブルtestとインデックスtestidxがありソースからターゲットへSharePlexによる複製の設定がされているとします。
create table test (
id number,
id1 number,
id2 number,
name varchar2(10)
)
;
alter table test add primary key (id);
create unique index testidx on test (id1, id2);
ここでソース側でテーブルへ行を追加します。
insert into test values (1,1,1,’test’);
insert into test values (2,2,1,’test’);
commit;
次に以下のようなCASE付きのUpdateを実行します
update test set id1= case when id=1 then 2 when id=2 then 1 else id1 end where (id=1) or (id=2); commit;
ターゲット側で一意制約違反(ORA-00001)が発生して非同期となります。
ソース側ではOracleにより 一意制約違反が抑えられますが、
REDOログではUpdateする行数分だけそれぞれ1行の DMLとして記録されており、それを利用するSharePlexでは、
ターゲット側は次のような行ごとに異なるUPDATEを実行することで一意制約違反が生じてしまいます。
update test set id1=1 where id=2;
commit;
仕様上サポートされない操作です。
SharePlex 側の設定で回避する方法はございません。
このようなUPDATE文が実行されてしまった場合には 一旦Out of Sync を無視して repair による修復することができます。
日常的にこのようなUPDATE文が実施される場合は、運用回避は難しいといえます。
回避策:
・ターゲット側でユニークインデックスを遅延制約 あるいは ユニークではないインデックスへ変更する
(あくまでも制約によるエラーを回避することが目的であり複製先で変更を受け入れられるかどうかは考慮しておりません)
・このようなSQLを実行しない
Error YYYY-MM-DD hh:mm:ss.720580 31020 3694831360 s:5 Table "APPDBUSER"."TEST" out of sync for queue upctest at source rowid AAASBjAAMAAAAGtAAA: ORA-00001: unique constraint (APPDBUSER.TESTIDX) violated (posting from o.opnet109, queue upctest, to o.orcl) Error YYYY-MM-DD hh:mm:ss.755484 31020 3694831360 s:5 Table "APPDBUSER"."TEST" out of sync for queue upctest at source rowid AAASBjAAMAAAAGtAAB: ORA-00001: unique constraint (APPDBUSER.TESTIDX) violated (posting from o.opnet109, queue upctest, to o.orcl)