ORACLEの面倒な仕様(分散トランザクション)
1つのトランザクション内で
DBリンク経由等から異なるインスタンスのデータを"参照"(SELECT)した場合、
そのトランザクションは「分散トランザクション」になる。
通常のJDBCからの接続(OracleDataSourceとか)でもそうなる。
ただOracleXADataSourceからConnectionつくると
「別インスタンスの」という条件を満たさなくても分散トランザクションになる。
分散トランザクション中に何らかのLOCK解放待ちが発生した場合、
デフォルト設定値60秒でそのセッションでは
ORA-02049(分散トランザクションがロックを待機しています)が発生して(基本)落ちる。
※JAVAとかでエラーハンドリングをちゃんとしてれば回避できる。
この設定値は確かinit.oraにもっているので変更可能だが、(設定項目名は忘れた)
設定の反映にはDBの再起動を要する。
厄介なのは"参照"の部分だ。
SELECTしかしてないのにトランザクションが変わる。
これの解決方法は
別インスタンスのDBを参照した直後に何にもしてないけどとりあえず空のCOMMITを行うこと
だそうだ。
気持ち悪くて嫌だが有識者などから聞く限りそういうことらしい。
バッチなんかでは性能面を考慮して
長い処理を一発でCOMMITかけるように実装しているものもある。
そういう場合、こういうケースに遭遇することがある。
まあそういうケースにおいては
おそらく必要なデータの配置が誤ってるというのが妥当な線なんだろう。
(よく考えたらわざわざ別インスタンスに置いておく必要なくねえかそのテーブル、みたいな)
ただ運用中、しかも1年も2年もたってからそんなこと言われてもというのもあるし、
かといって途中で変にCOMMITいれたくない
=そのあと別の原因で落ちたときのリカバリ設計や運用を考慮する必要が出てくるし、
厄介な仕様である。
この仕様はORACLE7の頃から実装されたものらしいが
なんとなく、やりたいことはわかるのだが、
せめて"参照"の部分だけは除けなかったものか。
納得がいかない。(「DML全般」っていう括りがあるのかな?)
こっちはまだ何もしてないのに
バイキルト直後に条件反射のように凍てつく波動かましてくるボスに似ている。
もういいよそんならバイキルトなし(別インスタンス見ない)でやるから、
という「変な」あきらめムードにさせられる。
(まあドラクエならそのあと基本的に勝つからいいか)