運用時に発生するエラー
ORA-02049: タイムアウト: 分散トランザクションがロックを待機しています。
データベースリンクを直接使用しているトランザクションやシノニムなどを用いて間接的に行なっている
分散トランザクションにはロックのタイムアウトの設定が存在する。
初期化パラメータの distributed_lock_timeout (単位:秒/設定後、要再起動) に指定された時間内に
要求した(ロックされている)リソースを取得できない場合に、ORA-02049: 〜エラーとなる。
デフォルトのタイムアウト時間は 60 秒なので初期化パラメータを変更して待機時間を延長するか、
例外処理を施してリラン(RE-RUN) させるようにする。
もしくは、ロックの設計自体に大きな問題がある可能性も考えられる。ロックの設計の見直しやバッチ処理の
スケジュールの調整などの運用によるエラー回避も検討した方がよいかもしれない。
通常のトランザクションでのタイムアウト
自己参照しているデータベースリンクによる 仮想リモート表への INSERT のタイムアウト
ローカルなデータベース(データベースリンクを使用していない)上でのトランザクションは
ロックが解放されるまで何時間でも容赦なく待たされる。
正当な待機時間をユーザーが制御する(おそらく)唯一の方法は SELECT 文の FOR UPDATE 句 による NOTWAIT、WAIT [ n 秒 ] の構文
だろうと思う。限定された状況下であれば ユーザーロックが使用できる。⇒ DBMS_LOCK.SLEEP 使用例
そこで、この分散トランザクションのタイムアウトを使用して FOR UPDATE 句では実現できない INSERT のタイムアウトを
実装できるか実験してみた。
データベースリンクを自分自身のデータベースに向けてループバックして定義し、競合する INSERT の行なってみたところ、
このタイムアウトが有効に働いてエラーとなった。(Oracle 10g 時点)
この仕組みとデータベースリンクをカプセル化するシノニムを併用することで DML のタイムアウトを実装するという
アイディアは面白そうではあるものの、そんな方法もあるね程度に留めておいた方がよいだろうと思う。
一覧ページへ戻る
OTN (Oracle Technology Network)によるエラーメッセージによる情報だけでは、対処に困ったエラーについてのプラクティスです。
ベスト・プラクティスというわけではないので、書いてあることに固執しないで広い視野でエラー対応してください。