[ Oracle ] SELECT FOR UPDATE 悲観的ロックによる損失は数千万円

Pocket

Oracle は多くの大企業で採用されているデータベースです。保守料も高額ですので大企業くらいしか導入できないのことが実際のところではないでしょうか。保守料のかからない無償版という選択肢もありますが、以下のような制約もあるので使い辛いのではないでしょうか。

スポンサーリンク

Oracle Database 11g Release 2 Express Edition の制約

  • サーバー:搭載CPU制限なし
  • CPU:最大1CPUが使用可能
  • メモリ:最大1GBが使用可能
  • データベースサイズ:最大11GBが使用可能(10g XE は最大4GBでした)
  • 対応OS:Windows 32bit, Linux 64bit

変更されていたりするかもしれませんので、あしからず

 

とある有名な SIer が開発した高額なシステムの話

とある大手の SIer が作った超高額なシステムでの実際の話ですが、反面教師として記録しておきます。でも、本当は記録しなくても忘れることができないと思います。 それはそれは悲惨なものでしたので。。。データベースには Oracle を使用していましたが、Oracle は直接関係ありません。

SELECT FOR UPDATE を使用して悲観的ロックが開放されないままになることで、ラインに導入されているアプリケーションが一斉に動かなくなることが度々発生しました。

  1. SELECT FOR UPDATE で悲観的ロック
  2. ダイアログでユーザーに実行確認 ( はい or いいえ )
  3. 処理実行
  4. ロック開放

これだけで十分に伝わると思いますが、問題は実行確認ダイアログを出しっぱなしのまま放置できてしまう点です。 ユーザーがご飯を食べに行くことも、一服休憩のために現場を離れることもあります。

他の端末から何か操作しようとしても、ロックがかかったままなので待ち状態となります。うんともすんとも応答がなくなってしまいます。サポートには、電話がなりっぱなしの状態になります。悲惨です。

とある有名な SIer の対応

じゃんじゃん電話がサポートに入ります。いろいろ調べてロックしている SQL やら端末を特定します。ダイアログを閉じてとりあえず解決しましたが、SIer は仕様と言い出す始末です。なかなか修正しようともしません。現場からはトラブルのたびに罵声が飛んできます。確認ダイアログを出したままの状態にしないようにお願いします。しかし、周知されません。

以降も、何度か同じトラブルが発生しました。1ヵ月後ようやく SIer が修正することになりました。システム的には大した問題ではないかもしれませんが、使用する現場は 24 時間体制ってこともあり、ラインが止まるたびに大きな損失になっています。

1回につき、数千万円の損失だそうです。

悲観的ロックとか楽観的ロックとか

悲観的ロックとか楽観的ロックとかありますが、どちらも排他制御のことです。どのタイミングで制御をかけるかの違いです。以下のように排他制御のタイミングに違いがあります。また、ロックの実現方法は様々です。

  1. 一郎さんがデータを読み込み
  2. 次郎さんが同じデータを読み込み ← 悲観的ロックはこのタイミング
  3. 一郎さんがデータを更新
  4. 次郎さんが同じデータを更新 ← 楽観的ロックはこのタイミング

上記のように悲観的ロックは同じデータの参照もできないように排他制御します。先発の更新処理が完了するまで WAIT ( 待ち状態 ) にするか、エラーとするかなどは要件によって決めればよいです。また、楽観的ロックは同じデータの参照はできますが、後発のデータ更新時にはエラーとするように制御する方式です。

私の文章が下手な件について、それは仕様です。

スポンサーリンク


Pocket

3 thoughts on “[ Oracle ] SELECT FOR UPDATE 悲観的ロックによる損失は数千万円”

    1. まさお Post Author

      Oracle9 を使っていました。これは間違いないです。
      あまり細かいことは忘れましたが、VB6からの接続です(接続方法記憶なし)。
      また、SIerの説明の内容を元に記事にしていますが、未検証ですね(コードは確認しましたが)。
      Oracleでは本来どのような動きになるはずなのか教えて頂けると助かります。

  1. さわ

    悲観的ロックの使いかたとしては、データの矛盾を防ぐ意図で瞬間的に使うものであって、リクエストをまたぐのは信じられないですね。
    残高が10000円の口座から6000円引き出す処理が、複数の顧客から集中した場合にオーバーするのを防ぐとか。
    そういうピンポイントの使い方だけをしていれば普通は順次裁かれていくので、ロックにタイムアウトを設定し、古すぎるロックについては接続を切って無効とする設定ができるはずです。
    仮に確認ダイアログが無くても、画面がフリーズしたりバッテリーが落ちるなども考えられるので、タイムアウト無しの運用は考えにくいですね

Leave a Reply to 大石敦巳 Cancel Reply

Your email address will not be published. Required fields are marked *