• 締切済み

関数内の排他制御について

いつも的確な回答に助けられていますm( __ __ )m 以下のようなメソッドがあるとします。 function test() { 処理1: データベースから値を取得 処理2: 処理1 で取得した値に +1 する 処理3: 処理2 の結果をデータベースに書き込む } 【質問】 関数 test がクライアント A と B の2人からほぼ同時にアクセスされた時、以下のような事が起きてしまうと思います。 ・ A が 処理1 を実行 ・ A が 処理2 を実行 ・ B が 処理1 を実行 ・ A が 処理3 を実行 ・ B が 処理2 を実行 ・ B が 処理3 を実行 当然データベースにある値は期待通りの値ではないと思います。 期待する動きとしては、A が関数 test の全ての処理を抜けるまで B は入り口で待機させるというようなことを想像しているのですが、 こういった場合、どのように排他制御したら良いのでしょうか? 私は C# で排他制御を実装した経験があるのですが、 C# では同期オブジェクトを用意して lock を使ったり、 ManualResetEvent などを用いることで排他制御が可能でした。 PHP でそれらに匹敵するようなものは存在するのでしょうか?

  • PHP
  • 回答数1
  • ありがとう数1

みんなの回答

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

RDBの話ですよね? 単純にトランザクションで処理すればよいのでは?

conecoxxx
質問者

補足

あ!なるほど!! bigin ~ commit ってこういう時使うのですね!! うぅ・・まだまだ基礎勉強が必要ですね;; ところで、ついでに質問なのですが、 クライアント A が bigin してから commit まで1分かかるとして、 クライアント B がほぼ同時に来た場合は、B は1分待たされてから処理を行うというイメージでよろしいのでしょうか?

関連するQ&A

  • ファイルの排他制御について

    こんにちは。 Visual Studio 2005 のC#を使って、ファイルを加工するアプリを書いていますが、 ファイルの排他制御についてよく分らなくて困っています。 プログラムの構成としては、以下の通りです。 1:プログラムAがファイルXYZを作成します。 2:プログラムAとは別々に動く、プログラムBが、このファイルXYZを読み込んで データベースに書込む処理をします。 この処理で、もしもプログラムAがファイルXYZの作成中の時に、 プログラムBが同じタイミングでファイルXYZを開いてしまった場合、 ファイルが中途半端な状態で開いてしまうのではないかと思ってます。 こういう状態を回避するためにはどういう処理にすればよいのでしょうか? よろしくお願いいたします。

  • トリガに排他制御をかけたいのですが

    トリガに排他制御をかけたいのですが Oracleのトリガで、 トリガ内の処理に対して排他制御をおこないたいのですが、 どのように設定すればよいのでしょうか? トリガの内容は以下となります。 CREATE OR REPLACE TRIGGER TRI_TEST after update of (トリガの実行条件その1) on ORG_TBL FOR EACH ROW begin if (トリガの実行条件その2) THEN begin insert(実行される処理その1) EXCEPTION update(実行される処理その2) end; end if; end; / 上記の条件において、 「実行される処理その1」 「実行される処理その2」 を行っている最中に他からのアクセスをブロックをさせたく思っております。 本件の理由は 他からのアクセスで行われる処理が 「select(トリガによってデータが投入されてるテーブル)」 「truncate(トリガによってデータが投入されてるテーブル)」 を連続して行う処理のため、 排他を実行しなかった場合、 他からのアクセスの「select」と「truncate」の処理間に トリガによってレコードがinsertされた際に、 そのレコードがselectされなくなることを危惧しているためです。

  • 排他制御について

    質問します。 VB.NETとSQLServer2000を使用して受発注処理を作成したいのですが、排他制御について今悩んでいます。 レコードロックの動作についてなのですが、Aさんが「A01」のデータをレコードロックでデータを画面に表示している場合に、Bさんも(別PCにて)同様にレコードロックで「A01」のデータを表示することは可能なのでしょうか?(取得できるのか) 何方かご教授お願い致します。

  • JDBCでのトランザクション・排他制御

    初めまして。 まだ初心者の身なのですが質問させてもらいます。 サーブレット・jspでJDBCを使いデータベースとの処理を行って簡単なショッピングサイトのようなものを作っています。 まずsetAutocomit() = falseでトランザクションを開始し データベースのUPDATEを行って、最後に確定する場合comit キャンセルする場合rollbackとしています。 しかし1人のユーザーがトランザクションを行っている場合に他のユーザーからアクセスされた場合にデータベースのトランザクション中の値を取ってきたいのですが、どうしてもトランザクションでUPDATEされる前の値になってしまうのです。 これを防止するのが排他制御というものだというのは分かったのですが 実際のやり方については、結構調べたのですがあまり載っていませんでした。 データベースはMySQLを使っています。 よろしければJDBCでの排他制御についてのアドバイス、もしくは詳しく説明されているサイトなどございましたら是非教えてください。 よろしくお願いします。

  • SQLServerにおける、排他制御に関して質問です。

    SQLServerにおける、排他制御に関して質問です。 環境:  SQLサーバ  ・Windows 2003 Server SP2  ・SQL Server 2005 Standard Edition SP3  SQLクライアント  ・WindowsXP SP3  ・.NET Framework 3.5 SP1 VB.NET アプリ  DBアクセサ  ・ADO.NETを利用 ---------------------------------------------------------------------- 1.DBとのコネクションを確立        ・        ・        ・ 2.データベーストランザクションを開始(レベルはSerializable) 3.テーブルAに対してINSERTを実行   (テーブルAの主キーはオートインクリメント設定されている。) 4.3の結果、追加された主キーを取得するため、MAX()関数にて主キーの最大値(つまり、3で追加した行のはず)を取得 5.テーブルAを外部参照しているテーブルに対して、4で取得したテーブルAのキーを利用して、行を追加・更新などを行う。 6.コミットを行う。   (コネクションは、アプリケーションが終了するまで保持する・・・) ---------------------------------------------------------------------- この処理フローで実行していたシステムですが、 二つのクライアント(X,Y)から、同時に2からの処理が行われた際に排他されず、 Xが、Yが作成したレコードの主キー値を元に、5の更新を行ってしまいました。 ログを見ると、 2→成功 3→成功(別のレコードが作成された) 4→XがMAX関数にて、Yが作成したレコードの主キーを取得   ※処理そのものは成功しているが、論理的におかしい となっています。 論理的には、トランザクションをかけているので、3からの処理が同時に行われるはずはなく、 4で取得される番号も、それぞれが作成した行の主キー番号になるはずなのですが・・・。 論理的に見落としている点や、環境的な要因などで、考えられる原因はありますでしょうか・・・?

  • データベースに書き込むときの排他処理

    ASP3.0 IIS5.0 ASP初心者です。初心者の素朴な疑問なんですが、 ASPで、例えばWebページから入力された情報を、 Accessなどのデータベースに書き込むとき、 排他処理って必要ですよね? 一般的にどうやるのでしょうか? Application変数を使うのでしょうか? データベース自体に排他制御する機能があるのですか? よろしくお願いします。

  • 排他制御の方法

    現在、PWS+ASP+ACCESSを使用し開発を行っていますが排他制御で悩んでいます。 ASPは、ステートレスなセッションでの制御しか出来ないため、ページを表示後のデータの変更はスタンドアロンでの更新のような形になってしまうと思います。 以下のような方法で行っている実例を見たことがありますが、少なからず問題も抱えていると思います。 ・レコード毎に排他フラグを保持する ~ 処理がアベンドした場合にフラグが残る(一定時間後に解除という方法もありますが) ・レコード毎に更新時間を持ち、読込時の更新時間と更新時の更新時間とを比較し更新されていない時だけ更新をかける ~ 後に更新をかけようとした変更が無駄になる 上記の方法以外で、排他制御を実現させる良い方法はないのでしょうか。他の方法で実現しているときは、その方法を教えて頂けませんでしょうか。 ※PWS→IIS、ACCESS→SQLServerに変更する可能性はあります。 (セッションオブジェクト・アプリケーションオブジェクト等を使用しての実現方法など) 宜しくお願いします。

  • 排他ロックしたレコードが、別トランザクションから参照されてしまい困っています。

    SQL Server2000を使用し、 あるトランザクションで排他ロック(XLOCK)をかけたレコードが 他のトランザクションから共有ロックを使用し参照できてしまう状態は存在するのでしょうか? 排他ロックをかけたレコードが 他のトランザクションから参照できてしまい困っています。 現在、下記の環境で開発を行っております。 ・サーバ側 Windows Server2003 SQL Server2000(sp4) ・クライアント側 Windows Xp(sp3) jdk6.0 jdbc 3.0 Type4 以下が具体的な状況となります。 前提として、 ・二つのトランザクション(以下A、Bと表記します)が存在する。 ・AとBは別のユーザでコネクションを張っている。 ・autoCommitはfalseに設定している。 ・テーブルにプライマリキーやインデックスは張っていない。 ・レコードは10件。 ・分離レベルはREAD COMMITED (1)Aから、「SELECT * FROM TEST_TABLE WITH(XLOCK) 」を発行 (2)Bから、「SELECT * FROM TEST_TABLE」を発行 このような状況で、(1)、(2)の順で処理を行った場合に 私の認識では、(2)の検索時にタイムアウト等が発生するという認識です。 しかし、(2)のSQLは正常に終了し、(1)と同じデータが取得されてしまいます。 ◆その他、確認したこと ・(1)の処理直後に処理を停止し、Enterprise Managerでロックが取得されているか確認したところ、トランザクションAがすべてのレコードを排他ロック(X)していた。 ・(2)の処理直後にロックの状態を確認しても、やはりトランザクションAが、排他ロック(X)していた。 ・CSEを使いODBC経由で同様の操作を行った場合も同じ動作がおこる。 ・(1)WITH(XLOCK, TABLOCK)とすると(2)でデータが取得できなくなる。 ・(2)のSQLを「SELECT * FROM TEST_TABLE WHERE COLUMN01 > 0」のように指定するとタイムアウトする(期待通りの動き) ・(2)のSQLを「SELECT COLUMN01 FROM TEST_TABLE WHERE COLUMN01 > 0」のように指定すると、今度は、なぜか取得出来てしまう。 ・(1)と(2)の間にトランザクションAでUPDATEなどを行うと(COMMITはしない)(2)のSQLのWHERE句や取得するカラムに関係なく、(2)のSQLはタイムアウトする(当り前か。。。) いろいろ書きましたが、排他ロックされたレコードに 共有ロックはかけれないという認識なのですが、 そうではないのでしょうか? また、そうではない場合どういった場合に、 共有ロックが可能となるのでしょうか? SQL Serverの排他制御に詳しい方や 同じような現象に陥った方がいましたら、ご教授お願いします。

  • flock関数での排他制御

    外部ファイルを更新する処理を作成しています。 ファイル更新中にファイルロック(flock関数)をかけて、 ロック中という事ではじかれた場合はエラーを出力するという仕組みを考えています。 下記にように記述しているのですが、 ロック中で書きこめなかった場合 エラーを出力する事はできたのですが、 ファイルが全て消えてしまいます… この場合はファイルを元のままに保持していたいのですが… あつかましいお願いかとは思いますが、 以下のソースで訂正すべき箇所は何処でしょうか。 =============================    $fp = fopen ($filename, 'w');  // ファイルオープン    if (flock($fp, LOCK_SH)) {   // 排他的ロックを行う    fputs($fp, 'ABCD');    // 書込む    flock($fp, LOCK_UN);    // ロックを解放する    fclose ($fp);       // クローズ        $flg = 1;   // 書込フラグ    b

    • ベストアンサー
    • PHP
  • Excelの関数の意味を教えてください。

    Excel関数初心者です。 以下のふたつの関数の式の意味を教えてください。 どの値を見に行って、それに対してどのような処理を行なっているのかを、できるだけ、わかりやすく教えてください。 (1)=IF(ISERROR(VLOOKUP(A2,B$1:C1,2,0)),"",VLOOKUP(A2,B$1:C1,2,0))&B2 (2)=SUMPRODUCT(1*NOT(ISERROR(FIND(B2,$C$1:$C$15))),$D$1:$D$15)

専門家に質問してみよう