- ベストアンサー
同一レコード更新時の排他制御
Oracle9iです。 C/S開発で、VB.NETで画面を開発します。 DBの更新は、画面よりストアドプロシージャを使って行います。 複数ユーザが同一レコードを同時に参照し、同一レコードに対して更新された場合、参照時の更新日時と異なる場合はエラーとするよう設計されています。(つまり、後更新はエラー) この排他チェックロジックを画面側で実装しようとしておりますが、この排他チェックロジックを画面側で実装せずに、Oracleよりエラーレコードを受け取ることによる排他制御を行うことはできないでしょうか? ご教授のほどよろしくお願いいたします。 また、参考サイトあれば、その紹介だけでも助かります。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
内容からすると画面にデータを取得し、編集してDBを更新するといったアプリケーションですよね? このケースで、更新先勝ちの仕組みを作るには画面とストアドの両方で考慮が必要になります。 更新日時を排他項目として使用するなら、参照時に、更新日時も取得します。データ編集後、ストアドへのパラメータとして編集データ+参照時に取得した更新日時を渡します。ストアドでは、updateの条件句にパラメータの更新日時を付け加えてやれば、既に他のユーザーによって更新されていた場合は、更新件数=0件となります。 一般的には「楽観的排他制御」という考え方です。 排他制御に関しては、システムの規模や運用レベルによって数種類の実装方針がありますので、参考URLも見ておいてください。
その他の回答 (3)
- masusun
- ベストアンサー率15% (44/285)
私もNo.2だと思うのですが、それで不都合なのであれば もっと簡単な方法で。 DB上、レコードに"更新ユーザID"のような項目を設けておいて select → 画面表示 → 画面編集 → update のselectの前にselectするレコードにユーザID登録するように してしまってはどうでしょうか。 他ユーザに参照専用(読取専用)として画面表示させることも簡単ですよね。 いわゆるVSSなんかで言うところのチェックアウトの概念です。
お礼
うーん。業務ロックを使うまではいかないんですよねぇ。実際。でも、大変に参考になりました!ありがとうございました!
- k_o_r_o_c_h_a_n
- ベストアンサー率55% (526/942)
クライアントがトランザクションを区切らなければ、 更新目的でデータを参照した時点で、他のクライアントの 参照を抑制することは可能です。 select * from hoge where ~ with update; というように、"with update"付きであれば、select時点で、 他に同じレコードを"with update"付きで問い合わせているセッションがあれば、 トランザクションが終わるのを待ち合わせます。 待ち合わせをせずに、止めるのであれば、"with update nowait"とすることで、 即時に戻ってきます。(参照できなかったので、ora-xxxxのエラー付きです) これにより、参照~更新~コミットの区間における、複数セッションで同時処理は 抑制できますので、アプリケーション側で、更新日時をチェックするなどの方法は とらずに済みます。 参考までに、アプリ側で、日時のチェックを行っても、時間の精度の問題で、 同時処理を抑制しきれるとは言い切れません。 (サーバが速すぎると、参照~更新~コミットが、速すぎて、チェックしきれない) #1どの >SQLCODEにてORA-XXXXの部分のエラーコードが返ってきますので、 そんなの無理では?? 他セッションで、更新後コミットするまでの間しかエラーになりませんよ?
お礼
参照ロックですね。 そうすると、画面を使用するユーザには、更新目的参照 か 参照のみ か 選択させる必要があるということでしょうか? スプレッドシートで更新できる仕組みの場合は、表示レコード分ロックしてしまうので、ちょっときついかもしれません・・・。 でも、大変勉強になりました! ありがとうございました!
- 0KG00
- ベストアンサー率36% (334/913)
例外処理を組み込んでおけばSQLCODEにてORA-XXXXの部分のエラーコードが返ってきますので、それをみて排他ロックが掛かっていたら○○、という形でできたと思います。
お礼
え!? それだけでいいの? ・・・と、びっくりしました。 ありがとうございます! えっとすみません。。。これは、同一レコードに対して「同時更新」のケースでしょうか?
お礼
楽観的排他制御ですか? 初めて聞きました。。。 煩雑な排他チェックの大部分ををストアドに依存させるのですね? なるほど・・・。 ちょっとこの線でも検討してみます。 ありがとうございました!