goo blog サービス終了のお知らせ 

へたれエンジニア日記(旧跡地)

こちらへ引っ越しました。http://d.hatena.ne.jp/toritori0318/

ORACLE小話その14 ライブラリキャッシュでデッドロック?

2007-08-10 23:52:17 | ORACLE・MSDE・Postgres
以前、ロックのお話をしましたが…


普通、デッドロックといえば
ORA-00060 リソース待機の間にデッドロックが検出されました。
ですよね?
1つのテーブル内に対する更新で
2つのセッションがあべこべなロック待ちをしてしまい、
デッドロックが発生します。


でもこないだ発生したデッドロックはちょっと違うんです。

ORA-04020 オブジェクト 'テーブルA' をロックしようとしてデッドロックを検出しました。

テーブルでデッドロック?

ちなみに、同じ時刻でまったく別のテーブルに対しても同じ現象が発生していました。

ORA-04020 オブジェクト 'テーブルB' をロックしようとしてデッドロックを検出しました。

このテーブルAとテーブルB、全く関連性はありません
本当に何がなんだか…



まず夜間バッチで一括ロードをしています。
その時、パラレルでテーブルAとテーブルBに対して
TRUNCATE→SQL*Loader(TRUNCATEは、ロードのオプションで行っている)
を行っているのですが、そのTRUNCATE中にデッドロックが発生した模様。
つかテーブルに対するデッドロックって意味わからん。

テーブルの状態としては、TRUNCATEのみが実行された感じでロードが動かず、
テーブルがどちらも0件のままになっていました。
一応、ORACLEマニュアルの対処法にもある通り
時間を置いて再実行したらうまく行ったみたいなのですが…。




トレースファイルを見てみると、以下のような循環ロックが発生していたようです。

セッション①がテーブルAに対し共有ロックしようとしたところ、セッション④によるロックによりブロック。
セッション②がテーブルBに対し排他ロックしようとしたところ、セッション①によるロックによりブロック。
セッション③がテーブルBに対し共有ロックしようとしたところ、セッション②によるロックによりブロック。
セッション④がテーブルAに対し排他ロックしようとしたところ、セッション③によるロックによりブロック。

つまり4つのセッションが互いのオブジェクトをロックしようとしたところでエラーが発生。
この内、2つの排他ロックというのは
並列実行のSQL*LoaderによるTRUNCATEだと推測されます。

問題は残りの2つ。
もうセッション情報が残っていないので調べようが無いのですが
おそらくはなんらかの他アプリケーションにより実行されたもので、
不正終了か何かでライブラリ内のオブジェクトをロックしたまま残ってしまい
オブジェクトを掴んだままになってしまったと思われます。
…もしくは、Oracle側の不具合w


と言いますのも、いろいろ検索してみたのですが
このエラー番号で調べてみると
ORACLEの不具合で発生してる事象がほとんどでした。
まあその場合、PL/SQL関連の不具合なので今回のとは少し違うんですけどね…。
しかもこのデッドロックって、ライブラリキャッシュ内で発生してるようなので
あまりこちら側で意識できない所のような気がするんですが。


レアケースみたいなので
とりあえずほって置くということでw

最新の画像もっと見る