• ベストアンサー

DBへの重複更新を防ぐ方法について

いつも、お世話になっております。 現在、ASP.NetとOracle9iでWebアプリケーションを開発しています。 現在、複数のユーザがほぼ同時に同一のデータに更新をかけられないよう にする処理で悩んでいます。 今まで開発してきたシステムでは、各データに更新回数を持たして、 その数をチェックすることにより、同時に更新されることを防いできました。 具体的には、 ユーザA:データ取得(このときの更新回数X) ユーザB:データ取得(このときの更新回数X) (ユーザA,B共に画面などで、データ操作) ユーザA:トランザクション開始 このとき、取得した更新回数を再度取得、X ユーザAが先に取得したときと更新回数が同一のため、データは更新されていない。 データ更新処理を許可する データ更新を行い、更新回数を+1する コミット ユーザB:トランザクション開始 このとき、取得した更新回数を再度取得、X+1 ユーザBが先に取得したときと更新回数が同一でないため、データは更新されている データの更新は許可しない ロールバック という処理を行っています。 しかし、この方法では、ユーザAがデータ更新を行う直前でかつ、ユーザBが更新回数のチェックを行うというタイミングだと、ユーザBがデータの更新ができてしまうようです。 より安全に重複更新を避けたいのですが、良い手はございませんか?ご存知でしたら、教えていただけないでしょうか?宜しくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • enzo_taku
  • ベストアンサー率47% (9/19)
回答No.1

排他制御はそれぞれの業務により向き不向きがあるため、一概にこうした方がよい...とは言えないですが。。。 http://www.atmarkit.co.jp/fdotnet/entwebapp/entwebapp11/entwebapp11_01.html # 自分であれば更新日時を保持し SELECT FOR UPDATE 使うかな

kiyohu16
質問者

お礼

会社からログインできないので、返信が遅くなってしまいまいました。 @ITのページを参考にさせて頂きました。 ありがとうございました。

その他の回答 (1)

回答No.2

更新日時が記録されてるならそれを利用するとか。 あとは、ADO.NET の DataAdapter コントロールに自動的に UpdateCommand を作らせると、全ての列を比較して更新する SQL 文と作ります。(相手が SQL Server の場合しか経験ないですけど)

kiyohu16
質問者

お礼

返信が遅くなってしまいました。 打合せの参考にさせて頂きました。 ありがとうございました。

関連するQ&A

  • 同一トランザクションの中でテーブルの更新結果を参照できるか?

    VB5.0+SQL-Serverで、以下のような処理を 検討しているのですが、いい方法がみつかりません。 つまり、同一トランザクションの中で更新結果を 参照することが出来るのでしょうか? ご教授いただけると幸いです。 【検討中の処理】 トランザクション開始(BegenTrans)  テーブルA更新  テーブルAの更新結果を参照してテーブルBを更新 (この時点ではトランザクションを終了していないので、  テーブルAの更新結果が参照できない) トランザクション終了(CommitTrans)

  • エラーについて(更新)

    Txtファイルには 1,A ~ 10,A のデータが入ってます。 データベースはmysqlで mysqlにはフィールドは ID NAMEで 1  1 ~ 9  1 のデータ9つが入ってます。 Txtファイルの10番目のデータを更新させると データベースにそれに対応したコードがないため エラーが出るはずなのですが、 エラーの形が次のようになります。 データが登録されました。データが登録されました。アクティブなトランザクションがありません。 アクティブなトランザクションがありません。 アクティブなトランザクションがありません。 アクティブなトランザクションがありません。 アクティブなトランザクションがありません。 アクティブなトランザクションがありません。 アクティブなトランザクションがありません。 アクティブなトランザクションがありません 何故なのでしょうか? 自分ではtxtファイルの10番目のデータを更新するときにだけエラーがでると考えているのですがそのように 動作してくれません。何故そのように動作しないのでしょうか?また、エラーがでているにもかかわらず 更新処理は全て正常に動作しています。 コードについても載せたいのですが 文字数制限で載せることができませんので 回答していただいた後に、補足で載せさせて頂きたい と思います。

  • トランザクションを張って対話型でのコミット・ロール

    トランザクションを張って更新処理を行った後に、 ユーザの「はい」「いいえ」ボタンによって、 トランザクションのコミットとロールバックを切り替えることは可能でしょうか。 処理の流れは以下の様になります。 1.データ更新前の値を取得 2.トランザクションの開始 3.データ更新 4.データ更新前の値とデータ更新後の値を比較して、   差分がある場合は確認メッセージを表示する。 5.確認メッセージで「はい」がクリックされた場合はコミットする。 6.確認メッセージで「いいえ」がクリックされた場合はロールバックする。 実装方法はどのようでも構いません。 どなたかご教授ください。

  • Perl JavaScript リアルタイム更新

    (1)サーバー側に置いてあるファイルの最終更新日時を取得 --> (2)へ 例)<--ここがPerlの処理? /test/log.txt --> 更新日時 2017/10/19 19:12 (2)-(1)ページに入った時間より新しければ、ページ更新 例)<--ここはJavaScriptの処理? /test/log.txt --> 更新日時 2017/10/19 20:25 (2)-(2)ファイルが更新されなければ、そのまま ユーザーA、ユーザーBが同時に掲示版を閲覧 ユーザーAが書込。 閲覧中のユーザーBのページがリアルタイムで更新 調べればWebSocketやSSLなどでてはくるのですが、 使えません・・・ ※私の技量・・・

  • postgreSQLで更新後のデータを取得したい。

    postgreSQLで更新後のデータを取得したい。 初めて質問させていただきます。 postgreSQLでupdateした後、更新後のデータをselectで取得したいのですが、 トランザクションが完了するまでにselect文が発行されているみたいで、更新前のデータを取得してしまいます。 それぞれ、違うファイルから投げられているので、同じトランザクションにすることはできません。 何かいい方法があればご教授お願いします。 a.phpで下記のSQLを発行 update test_tbl set test1 = 'aaa' where test2 = 'bbb' a.phpが走っている間に、下記のb.phpが実行される。 select test1 from test_tbl 環境 php5 postgres8.1

  • テーブルコピー処理

    早速質問させていただきます。 VB2005+MSDE2000でWindowsアプリを作成しています。 Aテーブル(本番テーブル)とBテーブル(ミラーテーブル)がありまして、 BテーブルはAテーブルと同列を持っており最終列に更新時刻が追加されています。そしてAとBともに年月列(200610等)を持っています。 実現したい処理は、年月度の売上データをミラーテーブルにコピーする処理です。 1.年月を元にAテーブルからデータを抽出する。 2.Bテーブルに対してトランザクションをかける。 3.年月を元にBテーブルから削除する。 4.1で取得したデータをBテーブルに追加する。  (この時、Bテーブルの最終列に更新時刻を入れる。) このような処理を行う際に、処理1は単純にセレクトなのでSqlDataAdapterでDataTableに流し込むのが最適かなと思います。 処理2についてもSqlTransactionを開始すればOK。 処理3はトランザクション内で削除を実施。 最後の処理4をどのように実装すればよいのか不明です。 SqlDataAdapterを使って処理1で取得したDataTableをBテーブルに追加したいのですが可能でしょうか? このあたりを具体的にご教授のほどお願い致します。

  • トランザクションの考え方

    トランザクションの考え方を教えて下さい。 「データの参照や追加・更新・削除といった処理に矛盾がないことを保証する」という記述を見たのですが、下記の場合も良いのでしょうか。 トランザクションの開始 SELECT * FROM Aテーブル WHERE 項目A = '1' --処理-- UPDATE Aテーブル SET 項目B = '2' WHERE 項目A = '1' トランザクションの終了 開始から終了までの間に他のPCによって SELECT対象のデータが増える可能性があります。 この場合UPDATEするときはやはりSELECTの結果でLOOPするべきなのでしょうか。 上記のようにするとSELECT件数とUPDATE件数は異なってしまうのでしょうか。 環境はVB2005+SQL Server です。

  • トランザクション中にSELECTした場合について

    InnoDBを使っているのですが、 以下の1.から5.の処理の間に、サーバー1.の「テーブルA」へ SELECTを掛けた場合、何か遅い気がします・・原因は何でしょうか? 1.サーバー1でトランザクション開始 2.サーバー1の「テーブルA」をDELETEでを全削除 3.サーバー2から「テーブルA」の新しいデータを取得 4.3.で取得したデータをサーバー1の「テーブルA」へINSERT 5.サーバー1でトランザクション終了 他のトランザクションでDELETEされたレコードに対し、 SELECTすると結果が返るのは遅いでしょうか?

    • ベストアンサー
    • MySQL
  • DBトラブルの解析方法について

    1、システム構成 (1)クライアント(Windows XP Professional) (1)VB6で作成した業務プログラム (2)oo4o(Oracle Object For Windows) (2)サーバ(HP-UX9000/800) (1)Oracle(DBMS) (ハードウェアが5台あり、ハードウェア毎にインスタンスが1つ作成済み。) (各インスタンスには、複数のユーザを作成済み。) (便宜上、各インスタンスをA,B,C,D,Eと呼ぶ。) 2、業務プログラムのoo4oを利用したDBAの流れについて 以下で挙げる処理1~4を順番に、GUIからの入力で実行します。 (1)処理1 (1)セションAを開始して、インスタンスAに接続。 (2)セションAからインスタンスAの複数の表の1レコードをロックする。 (3)セションAからDBリンクを利用して インスタンスBのオブジェクト(表など)を参照する。 (2)処理2 (1)セションBを開始して、インスタンスCに接続する。 (2)セションBからインスタンスCの1つの表1レコード参照してロックする。 (3)セションBからロックしたレコードを更新する。 (4)セションBをコミットする。 (3)処理3 (1)オペレーションCを開始して、インスタンスCに接続する。 (2)セションCからインスタンスCの複数の表の1レコード参照してロックする。 (3)セションCからインスタンスCの複数の表の登録・更新 (4)処理4 (1)セションAをコミットする。 (2)セションBをコミットする。

  • PCとDBを更新したら、エラーが発生するように。。

    約5年ほど前に開発されたDBを使用したシステムがあるのですが、サーバPCが故障し、PCとDBを更新しました。それから「タイムアウト」や「デッドロックエラー」が発生するようになりました。 【更新前】 1.サーバ  ・OS:Windows2000Server  ・DB:MSDE2000 SP3 2.クライアント  ・OS:Windows XP SP3(導入当初は、Windows2000)  ・アプリケーション:VC++6.0にて開発  ・7クライアント  ・ODBCにて接続 【更新後】 1.サーバ  ・OS:Windows Server 2008  ・DB:SQL Server 2008 Express Edition 2.クライアント  ・OS:Windows XP SP3(導入当初は、Windows2000)  ・アプリケーション:VC++6.0にて開発  ・7クライアント  ・ODBCにて接続  ※クライアント側は何も変わっていません。 発生するエラーは、以下の2つです。 (1)タイムアウトしました。 (2)トランザクション(プロセスID○○)が、ロック 個のリソースで他のプロセスとデッドロックして、このトランザクションの対象となりました。トランザクションを再実行して下さい。 サーバPCが故障した際、蓄積されていたデータをかなり削除した為、早くなる事はあっても、遅くなる?とは夢にも思いませんでした。当然、更新後のPCも5年前よりかなり早くなっているハズですし...。 営業からは、早くなんとかして欲しいと言われますが、未だに解決の糸口が見付かりません。 どなたか助言をお願い致します。

専門家に質問してみよう