• 締切済み

Select文とデッドロックについて

現在のような処理をしています。 SQL Server2008 R2 Expless プログラム1  select count(*) from TABLE_A プログラム2 BeginTrance SERIALIZABLE  select count(*) from TABLE_A Update TABLE_B set F1=123 Where P1=1 Commit ※ここで P1はTABLE_Bのプライマリキーとします。 この2つのプログラムを同時に実行している時に、プログラム1のSELECT文でデッドロックが発生した との連絡ありました。 プログラム2でもエラーが発生しているのかもしれませんが、現状調査不可能為不明です。 いろいろデッドロック、ロックヒントなどいろいろ調べてみた結果、なんとなく発生するかも?とは思われますが、このような場合、本当にデッドロックが発生するのでしょうか? また、発生する場合には、何と何がデッドロックになっているのでしょうか? (発生するはずがないとなると調査する視点を変えてみます。) よろしくお願いします。

みんなの回答

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.1

質問の内容だけならデッドロックは起こりえないと思いますが。 デッドロック: http://e-words.jp/w/E38387E38383E38389E383ADE38383E382AF.html デッドロックがおきる例 プログラム1 begintrans ・・・ update table_A set A1 = 1 update table_B set B1 = 2 commit プログラム2 begintrans ・・・ update table_B set B2 = 5 update table_A set A2 = 3 commit プログラム1は、プログラム2のupdate B set B2 = 5がcommitされるのを待っていて プログラム2は、プログラム1のupdate A set A1 = 1がcommitされるのを待っていて どちらも永久に終了できない状態。 updateがselectになったとしても、テーブルロックされてしまっていると同じ状態になります。 でも、質問文の内容なら、プログラム1で table_Bを使っていないので、 プログラム1が、プログラム2がcommitしていないためにテーブルロックされてしまったTABLE_Aを selectするのにタイムアウトで失敗したということかと思われます。 (デッドロックではないのでプログラム2は正常終了し、  プログラム1も再度実行するとエラーにならない) SQL Server2008 R2 は確認していませんが、 SQL Serverはロックエスカレーションしてselectしているだけでテーブルロックになる場合が あります。 但し、select count(*)くらいでテーブルロックにまでエスカレーションするのかは疑問ですが。 (テーブルロックだけではなく、行ロックでも同一行を参照しているなら起こりえますが。)

関連するQ&A

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

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

  • デッドロックについて

    (Java + ベンダー製DB) 以下のような複数トランザクションを順番に実行した場合、 デッドロックが発生する可能性はあるのでしょうか? トランザクションA (隔離レベル:READ UNCOMMITTED) SELECT * FROM A ... トランザクションB (隔離レベル:READ UNCOMMITTED) SELECT * FROM A, B ... トランザクションC (隔離レベル:READ UNCOMMITTED) SELECT * FROM C, D ... 個々のトランザクションでは単なるSELECT文のみで、しかも 隔離レベルがREAD UNCOMMITTEDであれば デッドロックは起こりえないと思うのですが、 100多重ほどでテストが行われたところ デッドロックが発生しているとの事でした。 デッドロックが発生する原因として何が考えられるでしょうか? 個人的には、どこかで更新プログラムが実行されていたとしか 考えられないのですが・・ よろしくお願いします。

  • デッドロックに関しての質問

    分かる方いましたら宜しくお願い致します。 SQLサーバー2000を使用しているのですが、デッドロックが 発生する場合がございます。 使い方としては インサートするプログラムA SELECTをするプログラムB SELECTをするプログラムC の3本にてテストを行っております。 デッドロックを起こすプログラムは SELECTをかけているB、Cになります。 Aに関してはトランザクションをかけている為、 インサート中はB,Cを起動させてもSELECTを待機しているように見えます。 SELECT中はNOLOCKを指定してません。 (余計な情報を出さない為) 発生する時が稀で、タイミングによるものかの検討も ついておりません・・・ SELECT文同士でもデッドロックは発生するものですか?? 対処法など分かる方もいらしたら宜しくお願い致します。 乱雑な文章ではありますが、宜しくお願い致します。

  • 同じSELECT文同士でのデッドロックが発生

    ORACLE10Gを使用したアプリ開発中です。 アプリ中、1テーブルに対して全く同じ条件で 複数レコードを悲観的ロック(for update)しながら取得し、 項目を更新するSQLを発行します。 単発では問題なかったのですが、処理時間の関係で パラレルで実行された場合にデッドロックを検出することがあります。 ORACLEのudumpの中を確認すると全く同じSELECTのSQL同士で デッドロックが発生したと表示されています。 こういった場合、どういう原因が考えられるでしょうか? (同じ条件による悲観的ロックであれば多重実行でも  処理待ちをするだけだと思っているのですが・・・) よろしくお願いします。

  • Select文1 マイナス Select文2

    テーブルA ユーザーID,地名,県名,評価 テーブルB ユーザーID,県名,制覇flag のような二つのテーブルがあると仮定してSelect文1、 "select 県名,count(地名) from テーブルA where ユーザーID=1 group by 県名 order by count(地名);" の結果が 県名,count(地名) 北海道,30 東京,22 京都,15 名古屋,10 鳥取,9 沖縄,8 であるとし、 Select文2、 "select 県名 from テーブルB where usrid=1 and 制覇flag='true'" の結果が、 県名 北海道 東京 とします。 このSelect文1の結果から、Select文2の結果を引いて 県名,count(地名) 京都,15 名古屋,10 鳥取,9 沖縄,8 の結果を得るにはどうすればよいでしょうか? Mysqlのバージョンは5.0.21です。

    • ベストアンサー
    • MySQL
  • reindex と update のデッドロック

    実運用中のテーブルに対し、日次で reindex を実行したところ、時々、デッドロックが発生してしまいます。 どうやら、reindex と update の間でデッドロックが起きているようです。 エラーメッセージを見た感じでは、以下の状態でデッドロックになっているように読めます。 ・update がテーブルのインデックスに対するロックを取得し、テーブルに対する RowExclusiveLock を取得しようとしている ・reindex がテーブルに対するロックを取得し、テーブルのインデックスに対する AccessExclusiveLock を取得しようとしている ※ 参考までに、update は select for update してから update しています。 Postgre のバグではないかと思うのですが、デッドロックを回避する方法はありますでしょうか? (なるだけ、reindex を実行しているプロセスの方に手を入れることで対応できないかと思っています。例えば、reindexの前に事前にロックを取得する、とか・・・) よろしくお願い致します。

  • 一括テーブルロック デッドロック対策

    はじめまして。 ken7761227と申します。 SQL Server2008R2でデッドロックが発生しまして、本来であれば、テーブルの 参照、更新順を正しくする修正をすべきなのですが、今からその修正を行うのは 困難なために、更新する側が、使うテーブルをまずTABLOCKXでロックしておく という対策をとることになりました。 ここで、A,B二つのテーブルがあったとし、 SELECT XXX FROM dbo.TableA WITH( TABLOCKX ) UNION SELECT YYY FROM dbo.TableB WITH( TABLOCKX ) というSQLでロックしようとしています。 UNIONを用いたのは、2つのセレクトの間に違うプロセスからの割り込を 防止したかったためです。 (このSQLの実行時にトランザクションをかけて、更新後のコミットまで、 排他ロックをかけようとしています。) TableA,TableBを更新しようとしているプロセス1が、上記SQLを実行しオーナーになります。 プロセス2がTableBをSELECTしようとすると、排他ロックで待たされるはずですよね? 実際ここは待たされていました。 また、プロセス2も更新を行おうとし、上記のSQLを実行すれば、プロセス1のコミット までは、処理が待たされるはずだと思っていたのですが、ここでデッドロックしてしまいます。 原因が全く分からずに困っております。 最終的に、やりたいことは、テーブルの参照、更新の順番を変えずに、デッドロックを 回避することです。テーブルロックをかけかたが、間違っていますでしょうか? また、それ以外に何か良い回避方法がありますでしょうか? どなたか、有識者の方々のご助言頂けないでしょうか。 よろしくお願いいたします。

  • 二つのcount()を一文で

    Select count(COLUMN_A) from TABLE_A where USERID=1 and FLAGS=1; Select count(COLUMN_A) from TABLE_A where USERID=1 and FLAGS=2; を1つの文で取得する方法はないでしょうか?

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