SELECT FOR UPDATEについての質問

このQ&Aのポイント
  • SELECT FOR UPDATEを使用すべきか
  • SELECT FOR UPDATEのロック期間
  • SELECT FOR UPDATEの挙動
回答を見る
  • ベストアンサー

SELECT FOR UPDATE について

■SELECT FOR UPDATEとは、 複数のプログラムで在庫の更新などが行われる場合に、 使用するべきでしょうか? ■SELECT FOR UPDATEのロック期間は、他の更新が待たされるのは 下記2.~3.の間でしょうか? バッチ更新(5分) 1.トランザクション開始 2.SELECT FOR UPDATE 3.UPDATE 4.トランザクション終了 ■上記2.のSELECT FOR UPDATEがおこなれた時点のレコードに対し、  他の場所でSELECT FOR UPDATEした場合、  上記2.の時点のデータがSELECTされるのでしょうか?  それとも、上記3.が終わるまでSELECTを待つのでしょうか? DBは、MySQL5ですが、DB問わず同じ挙動と思い、 このカテゴリに質問されていただきました。

  • php4
  • お礼率42% (373/888)

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

  • ベストアンサー
回答No.2

#1回答者です。 #1回答にも書いたように、排他制御はRDBMSにより仕様差があります。一方で様々なオプションがあり、似たような制御にすることも可能です。 MySQLでも、ストレージエンジンの種類で排他単位が変わったり、排他制御の強さや区間を変える様々なオプションがあります。 MySQLについて調べてみました。 >複数のプログラムで在庫の更新などが行われる場合に、 >使用するべきでしょうか? 複数のユーザが接続する環境で、関連する複数の表、あるいは複数の行を検索、更新する場合に使います。 >SELECT FOR UPDATEのロック期間は、他の更新が待たされるのは >下記2.~3.の間でしょうか? FOR UPDATE指定でSELECT実行~トランザクション終了までです。 >上記2.のSELECT FOR UPDATEがおこなれた時点のレコードに対し、 >他の場所でSELECT FOR UPDATEした場合、 >上記2.の時点のデータがSELECTされるのでしょうか? >それとも、上記3.が終わるまでSELECTを待つのでしょうか? FOR UPDATE同士の検索が複数ユーザからあると、先に検索した側がその行を占有するため、後続ユーザは排他待ちになります。待ち解除されるのは、先行ユーザがCOMMITしてくれた時点です。 マニュアル参照先 http://dev.mysql.com/doc/refman/4.1/ja/commit.html http://dev.mysql.com/doc/refman/4.1/ja/innodb-locks-set.html http://dev.mysql.com/doc/refman/4.1/ja/innodb-transaction-model.html

php4
質問者

お礼

マニュアルの参照先までありがとうございます。 MySQLコマンドを2つ起動して、 やってみたところ、排他待ちになりました。 制御はRDBMSにより仕様差が結構あるのですね。。 1.BEGIN 2.処理 3.BEGIN でもコミットされてしまいました。 とりあえずファイルロックで逃げる事にしましたが、 ロックはなかなか奥が深く難しいですね。 DBを変えたら試行錯誤が必要と感じました。

その他の回答 (1)

回答No.1

>DBは、MySQL5ですが、DB問わず同じ挙動と思い、 >このカテゴリに質問されていただきました 排他制御の挙動は、RDBMS毎に相当な違いがあります。 MySQLについて知りたいなら、MySQLのカテゴリで質問してください。

関連するQ&A

  • select for updateのロック

    オラクルのselect for updateでロックをするタイミングがいつですか? こんなPL/SQLのコードがあったとします。 ---↓↓↓ソースコードここから↓↓↓------------------------- select * from テーブル1 where id = 1 for update; ・・・・・(a) ~ update テーブル1 set kingaku=100 where id = 1 ・・・・・(b) ~ commit; ---↑↑↑ソースコードここまで↑↑↑------------------------- id = 1のレコードがロックされるのは(a)、(b)どちらのタイミングですか? また、このロックは ・他トランザクションから読めるけど更新できない ・他トランザクションからは読むことすらできない のどちらでしょうか? よろしくお願いします。

  • SELECT FOR UPDATE にトランザクションは必要ですか?

    SELECT FOR UPDATE を使う時に、 SELECTの前でトランザクションを開始する必要はあるでしょうか? それとも、ただ、 SELECT FOR UPDATE UPDATE でも、行ロックされるでしょうか? そもそもトランザクションとは、 複数の更新がない場合は使う必要はないのでしょうか?

    • ベストアンサー
    • MySQL
  • SELECT FOR UPDATE で該当レコードがなかった場合

    SELECT FOR UPDATE ですが、該当レコードのみ ロックすると思うんですが、 該当レコードがない場合は、 ロックできないんでしょうか? たとえば、(COLUMN_BBB が PK として) SELECT * FROM TABLE_AAA WHERE TABLE_AAA.COLUMN_BBB = 'BBB' FOR UPDATE で、そもそも SELECT * FROM TABLE_AAA WHERE TABLE_AAA.COLUMN_BBB = 'BBB' となるレコードがない場合でも、 他トランザクションによる 該当レコードの INSERT を排他防御できるのか無理なのか、 教えていただけたらありがたいです。 すみません、時間的余裕があまりないので、 (すぐに回答ほしいです)でアップします。

  • 一つのトランザクションでSELECTとUPDATEできますか? (ADO.NET)

    いつもお世話になっております。 ADO.NETの話なのですが、トランザクションを開始したコネクションオブジェクトで DataAdapterを使ったSELECTと、ExecuteNonQueryを使ったUPDATEを交互に繰り返し 行うことはできるでしょうか? 現状できていないので可能なのであれば共通関数の見直しが必要かと思っています。 いまはSELECTとUPDATEを別のコネクションで行っているのですが、UPDATE後に 同じテーブルの該当レコードをSELECTにいくため、デッドロックが発生しています。

  • SELECT時の行ロックの必要性について

    SELECT ~ FOR UPDATEやSELECT ~ LOCK IN SHARE MODEという行ロックがあり、この件について解説しているサイトをいろいろ見ているのですが、振る舞いが複雑だということはわかりました。 しかしそもそもなぜSELECTで行ロックするのか、運用上でどんなときに使うのかを解説しているサイトは見当たりませんでした。 私は、SELECTするときは単に SELECT * FROM tb_a WHERE id = 1; としか記述していません。 質問1. なぜSELECTするのにトランザクションが必要なのでしょうか?運用上でどんなときにSELECTでトランザクションを使うのでしょうか?よく解説サイトには、 BEGIN; SELECT * FROM tb_a WHERE id = 1 FOR UPDATE; COMMIT; と書いています。SELECTするのに行をロックする必要性がいまいちわからないです。 質問2. トランザクションを開始したときにロックがかかるのではないのでしょうか?つまりBEGIN;でロックがかかるわけではないのですか?SELECTのクエリーにFOR UPDATEと書くということはこのSELECTのコードが実行された時点でロックがかかるのでしょうか? 質問3. FOR UPDATEやLOCK IN SHARE MODEというのはSELECTにしか使えないのか、もしくはSELECTだから意味があるのでしょうか?UPDATEやDELETEは単にBEGINE;とCOMMIT;で囲えばいいだけですよね? 質問4. 以下のようなコードを解説しているサイトがあります。 BEGIN; SELECT * FROM tb_a WHERE id = 1; COMMIT; SELECT文にはFOR UPDATEも書いていないのですが、これは何を意味するのでしょうか?つまり、SELECTするのになぜトランザクションを実行するのでしょうか? 一番知りたいのは運用上どのような場合にSELECTでトランザクションを使って行ロックするのか、ということです。 どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL
  • OIP-04129: SELECT FOR UPDATE

    OIP-04129: SELECT FOR UPDATEでのコミット/ロールバックを処理しています。 上記のエラーが理論的にどういう時に発生しますか? 自分が先に一つテーブルのデータを全部ロックしてますが、関係あるはずです。 原因が知りたいです。 宜しくお願いします!

  • DAOで同値更新するとException発生

    C++,DAO,MySQLで開発しています。 標記の通りなのですが、更新するレコードセットの値をDBのテーブルと 同じものでUPDATEしようとするとExceptionをスローします。 処理の大まかな流れは以下の通りです。 1. DBオープン (CDaoDatabase Open) 2. テーブルオープン (CDaoRecordset Open) 3. トランザクション開始 (BeginTransaction) 4. レコードセットを移動 (FindFirst 何かしらの条件で) 5. 値を設定 (SetFieldValue) 6. レコード更新 (Update) 7. コミット (CommitTransaction) 5.の時点でDBと同じ値を設定した場合に 6.のステートでExceptionスローします。 (5.でDBと違う値なら最後の処理まで難なく通ります。) 4.の時点で意図しないindexに移動しているわけでもないので、5.での同値か異値かの問題であると思っていますが… どうすれば回避できるのでしょうか? ご教授方お願いします。。。。

  • DAOの操作をするとExceptionが発生する

    C++,DAO(MFC),MySQLで開発しています。 標記の通りなのですが、更新するレコードセットの値をDBのテーブルと 同じものでUPDATEしようとするとExceptionをスローします。 処理の大まかな流れは以下の通りです。 1. DBオープン (CDaoDatabase Open) 2. テーブルオープン (CDaoRecordset Open) 3. トランザクション開始 (BeginTransaction) 4. レコードセットを移動 (FindFirst 何かしらの条件で) 5. 値を設定 (SetFieldValue) 6. レコード更新 (Update) 7. コミット (CommitTransaction) 5.の時点でDBと同じ値を設定した場合に 6.のステートでExceptionスローします。 (5.でDBと違う値なら最後の処理まで難なく通ります。) 4.の時点で意図しないindexに移動しているわけでもないので、5.での同値か異値かの問題であると思っていますが… どうすれば回避できるのでしょうか? ご教授方お願いします。。。。

  • SELECT文でのデッドロックに対しての対処方

    先日よりデッドロックが発生するようになり、確認の為にトレースログを 抽出するように設定かけたのですが、UPDATE文とSELECT文がぶつかり デッドロックが発生している事がわかりました。 しかし、UPDATE文にはトランザクションをかけていますが SELECT文には特にロックかけていない為、どうして起こっているのか わかっていません。 SELECT文を読んでいる時にUPDATE文によって レコードに変更があった為、デッドロックが発生したのでしょうか? SELECT文にはUNLOCKをつけた方がいいのでしょうか? プログラムはDELPHI DBはSQLSERVER2000になります。 お忙しい所申し訳ありません。 宜しくお願い致します。

  • max+1で初番する場合 for updateは必要ですか?

    AutoIncrementでなく、 あるコードの中の最大値+1で番号を初番する場合、 1.トランザクション開始 2.select max(no) from master where aru_code = 1 for update 3.insert into master values (2で取得したnoとaru_code=1) 4.トランザクション終了 というように、for updateで行ロックをかけないと 同じ番号が初番されてしまう可能性があるでしょうか?

    • ベストアンサー
    • MySQL