• 締切済み

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)どちらのタイミングですか? また、このロックは ・他トランザクションから読めるけど更新できない ・他トランザクションからは読むことすらできない のどちらでしょうか? よろしくお願いします。

  • Oracle
  • 回答数2
  • ありがとう数13

みんなの回答

  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.2

こんにちわ。 #1 のmuyoshid です。 > ちなみに、そのソースはどこかにありますでしょうか? この辺が参考になるでしょうか? SQL 言語リファレンスのfor update 句の説明です。 http://docs.oracle.com/cd/E16338_01/server.112/b56299/statements_10002.htm#i2066346 > 別の人を説得しなければいけないのです。 そうであれば、ユーザ登録が必要ですがOTN Japan から試用版をDownload して 実際に動かして確認した方が良いと思います。

参考URL:
http://www.oracle.com/technetwork/jp/index.html
  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.1

こんにちわ。 > id = 1のレコードがロックされるのは(a)、(b)どちらのタイミングですか? レコードがロックされるのは、(a) のタイミングです。 > また、このロックは > ・他トランザクションから読めるけど更新できない > ・他トランザクションからは読むことすらできない 他のトランザクションから読み込めますが、更新はできません。 また、(b) のupdate を実行しても、commit が完了するまでは 他のトランザクションからはUpdate 前のデータが読込まれます。

trap1130
質問者

お礼

ありがとうございます。 ちなみに、そのソースはどこかにありますでしょうか? 決して疑っているわけではなくて、 別の人を説得しなければいけないのです。 もうひとつ、(a)からcommitの間で、別のトランザクションが、 同じようにselect ~ for update を行うとエラーになりますよね?

関連するQ&A

  • 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
  • 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問わず同じ挙動と思い、 このカテゴリに質問されていただきました。

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

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

    • ベストアンサー
    • MySQL
  • ある条件の最大値+1を初番するにはロックが必要ですか?

    以下のテーブルでcolumn毎に連番を振る場合、 テーブルロックが必要でしょうか? テーブル test id column 1 a 2 a 1 b 新規データ登録手順 1.トランザクション 2.select max(id)+1 from test where column = b for update 3.insert test into (id,column) values (selectで取得した値,b) 4.トランザクション終了 これで、column毎に登録されているIDの最大値+1で 重複せずにデータのINSERTが保障されるでしょうか?

    • ベストアンサー
    • MySQL
  • 行ロックについて

    Web上のボタンをクリックしたとき 該当データを1件取得しそのデータにフラグをたてる ⇒フラグを管理するテーブルに投入する という処理をしており該当データは一人につき1件取得したいです。 BEGIN SELECT * FROM TABLE1 WHERE day = 今日 ORDER BY time LIMIT 1 FOR UPDATE UPDATE TABLE1 SET flag = 1 WHERE id = $id INSERT INTO TABLE2 (time , flag ) VALUES ($time , 1); COMMIT 現在の問題は同時にボタンを押したとき SELECTで取得したデータが重複してしまうことがあることです。 BEGINからCOMMITまでを一連の流れとし、 その間はSELECTもできないようにしたいです。 ドキュメントに FOR UPDATEだとUPDATE、DELETE、SELECT FOR UPDATEは拒否されます とありますのでSELECTは通ると解釈するとFOR UPDATEでは実現できないのでしょうか? テーブルのロックではなく行のロックで実現したいのですが どなたかご教授お願い致します。 ※バージョンはPostgreSQL 8.1.18 です。

  • 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 を排他防御できるのか無理なのか、 教えていただけたらありがたいです。 すみません、時間的余裕があまりないので、 (すぐに回答ほしいです)でアップします。

  • PHP+MYSQL BEGIN;とCOMMIT;

    下記のSQL文をPHPで書くとどの様になりますでしょうか? オブジェクト指向でお願いします。 BEGIN; // トランザクションA開始 SELECT * FROM users WHERE id = 1 FOR UPDATE; COMMIT; // トランザクションA終了

    • 締切済み
    • PHP
  • デットロックとFOR UPDATE

    こんにちは。 PostgreSQLのマニュアルを見ますと。次のような文の組み合わせはデットロックになる可能性があるとされてます。 プロセス1 UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222; UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111; プロセス2 UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111; UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222; #PostgreSQL8.1.5のマニュアルの12.3.3を参照しています。 #http://www.postgresql.jp/document/pg815doc/html/explicit-locking.html#LOCKING-DEADLOCKS こういった場合の回避方法なのですが、 プロセス1 SELECT * FROM accounts WHERE acctnum=11111 AND acctnum = 22222 FOR UPDATE; UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222; UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111; プロセス2 SELECT * FROM accounts WHERE acctnum=22222 AND acctnum = 11111 FOR UPDATE; UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111; UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222; とするのは大丈夫なのでしょうか? 本来なら、マニュアルにもある通り、UPDATEの順番を揃えるのがいいのでしょうが、実際にはWHEREの部分が変数で変化してしまうため、少々手間なのです。 実際のところ、このような場合、SELECT ~ FOR UPDATEで大丈夫なのでしょうか?それともテーブルレベルロックを用いるべきでしょうか?あるいはソートを用いるなどしてでも順番をそろえるべきなのでしょうか? 実際の処理はpl/pgsqlの関数の中で、EXECUTE文によって行っています。 なので、なるべく複雑な処理は避けたいところなのです。 できれば情報ソースなども示してご説明いただけるとありがたいです。よろしくお願いいます。

  • SQLでSELECTした一覧をUPDATEする方法を教えてください。

    AのテーブルをINNER JOINのWHERE文を用いて、selectした結果の項目にBテーブルの内容をUPDATEしたいのですが、 下記方法でうまくいきません。 解決方法を教えてください。 よろしくお願いいたします。 SELECT A.PointZan FROM A INNER JOIN B ON A.Code = B.Code WHERE (B.TrDate = '091012') AND (B.Comment = '失効中止') UPDATE A SET PointZan = (SELECT B.PointZan FROM B INNER JOIN A ON B.Code = A.Code WHERE (B.TrDate = '091012') AND (B.Comment = '失効中止'))

  • ロックについて

    データベース初心者ですが、よろしくお願いします。 トランザクション処理のロック制御について質問です。 例えば、ユーザAが表に対しupdateを行い、commitを行わなかったとします。このときに、他のユーザBがその表に対しupdateを行った場合、エラーになるのでしょうか? 私は、トランザクション処理というのは、表操作を行ってからcommitするまでの間をひとくくりとして、その間はロックがかかると認識しています。 どなたかご教授願います。