
はじめまして。
SQL SERVER初心者の為、ご指導の程お願いいたします。
UPDATE文で発生するデッドロックについて教えてください。
現在、ストアドプロシージャ内で、
以下のUPDATE文を使用しています。
UPDATEテーブルA
SET 更新済フラグ='1'
WHEREロック時間 =パラメータ.ロック時間
ANDロックユーザー=パラメータ.ロックユーザー
AND ID= パラメータ.ID
※Where句に使用する、ロック時間・ロックユーザー・IDは、
キー項目では無く、インデックスも使用しておりません。
ただし、対象データを一意に識別できる項目ではあります。
このストアドを含む処理を、ほぼ同時実行すると
このUPDATE文で「LOCK TIMEOUT」が発生し、
デッドロックとなってしまいます。
UPDATEの対象となるデータ件数は、ともに500~600件です
また、対策としましてロックのヒント文を下記のように設定し、
WHERE句に設定している、ロック時間・ロックユーザー・IDに
対して、インデックスを作成してみましたが、
同様に、デッドロックが発生してしまいます。
UPDATEテーブルA (with rowlock)
SET 更新済フラグ='1'
WHEREロック時間 =パラメータ.ロック時間
ANDロックユーザー=パラメータ.ロックユーザー
AND ID= パラメータ.ID
SQL Serverに詳しい方、お力になっていただければ、光栄です。
よろしくお願いいたします。
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
回答が遅れました。
色々なアドバイスが出てきていますので、一度切り分けて
考えてみてはいかがでしょうか。
・SPから当該UPDATE文のみを抜き出して実行してもデッドロックになるか?
・TABLOCKにした場合でも同じか?
・ロックの待ち時間を長くしてみてもTIMEOUTが発生するか?
をまずは試してみてください。
その結果によって原因がわかるかもしれませんし、
別のアドバイスが出来るかもしれません。
No.6
- 回答日時:
SQLServerは、
重複していなく、インデックスになっているキー(主キー含む)、
に対して、WHERE句を設定すると行ロックとなり、
重複している OR インデックスになっていない、フィールドに対して、
WHERE句を設定するとページロックまたは、全件検索となる仕組となっています。
デッドロックは、複数のSQL文が発行された時におきる現象ですが、
今回、この「UPDATE」以外の、SQL文はどうなのでしょうか?
基本的にSQLServerは、適切なテーブル設計、チューニングができていれば目だった、デッドロック、遅延等ほとんどおきないように、なってはいますが・・・
基本中基本が原因であれば、RDBのスキル習得からオススメします。
No.5
- 回答日時:
>Where句に使用する、ロック時間・ロックユーザー・IDは、
>キー項目では無く、インデックスも使用しておりません。
>ただし、対象データを一意に識別できる項目ではあります
あなたには一意と判断できても、RDBMS側には一意と判断できず、
全件検索することになります。
>このUPDATE文で「LOCK TIMEOUT」が発生し、
>デッドロックとなってしまいます
SQL Serverのデッドロックには詳しくないですが、RDBMSによっては
「たすき掛け」と「排他待ちが一定時間を越えた」を切り分けて
メッセージを出してくれるものも少なくありません。
今回の場合は、後者ではないのでしょうか?
>UPDATEの対象となるデータ件数は、ともに500~600件です
UPDATEを500~600件発行するとき、COMMITは発行していないのですよね?
インデクスがなければ、物理順で同じ経路を繰り返し探すことになるので
タイムアウト等が発生して当然だと思いますが?
>ロック時間・ロックユーザー・IDに
>対して、インデックスを作成してみました
どういうインデクスを定義したのでしょうか?
(ロック時間,ロックユーザー,ID)で1本のインデクスを定義したの
でしょうか?
chukenkenkouさん、ご返答ありがとうございます。
いくつかご回答につきまして、いくつか質問をさせてください。
>あなたには一意と判断できても、RDBMS側には一意と判断できず、
全件検索することになります。
これについてですが、ロック時間・ロックユーザー・IDが、
テーブルのキー項目となっている場合は、全件検索は行われない
という認識でよろしいでしょうか?
初歩的な質問で申し訳ありません。
>どういうインデクスを定義したのでしょうか?
>(ロック時間,ロックユーザー,ID)で1本のインデクスを定義したの
でしょうか?
なにぶん初心者なもので、インデックスの作成は手探り状態で
行いました。
エンタープライズマネージャーより、該当テーブルのデザインより、
(ロック時間,ロックユーザー,ID)のインデックスを作成しました。
1本のインデックスも作成することが可能なのですか???
また、インデックスのよい作成方法をご存知であれば、
教えてください。
現在、下記のようなテーブルレイアウトです。
識別コード,年度,月度,○○番号 ・・・・・ ロック時間,ロックユーザー,ID
※識別コード,年度,月度,○○番号までが、キー項目となります。
よろしくお願いします。
No.4
- 回答日時:
自分も初心者ではありますが同じようなことがあったので参考までに書かせていただきます。
確かLOCKTIMEOUTはデッドロックではなかったような気がします。
LOCKTIMEOUTということは順序的に先になった更新処理が遅すぎて後続が待ちきれずにTIMEOUTしたのではないでしょうか?
トランザクション開始処理時のオプションで処理待ち時間が変えられるはずなので、試してみてはいかがでしょうか?
以上、参考になれば幸いです。
No.3
- 回答日時:
再度#1です。
SQL Serverの環境が手元に無いので試していませんが、
With句の指定って
×:UPDATE テーブルA (with rowlock)
↓
○:UPDATE テーブルA with (rowlock)
じゃないかなぁ・・・
ちゃんと行ロックになっているか、EnterPriseManagerなり
sp_lockで見るなりして確認してみてください。
この回答への補足
ご回答ありがとうございます。
すみません。記述を間違えていました。
プログラム上は、with (rowlock)となっています。
No.2
- 回答日時:
#1です。
追加質問にお答えします。SQL Serverは通常、ページ単位のロックを行います。
(確か7.0からはオプティマイザが動的に最適なロック単位を
選択してくれるようになったかも・・・)
ですので、行A・Xが違っても同一ページ(確かデフォルトは8KB)に
入っていれば、Aを更新ロックする際にXもロックされます。
しかし、行ロックオプションを指定しているとのことですので
それは起こらないはず。なのでTransactionを開放してないからとか
ストアド内で他のテーブルも更新していて順序がたすきがけに
なったとか、の原因を疑った方が良いとおもいます。
早急なご回答ありがとうございます。
度々の質問で大変恐縮ですが、処理内容を確認したところ、、、
SP内の処理では、同一テーブルに更新しにいく処理は存在しますが、
同一行への更新は行われないものとなっています。
ヒント文、ROWLOCKを使用しておりますが、
同一テーブルへの更新が行われる場合、デッドロックの可能性が
考えられるということでしょうか???
よろしくお願いいたします。
No.1
- 回答日時:
Updateの行の順序は保証されていません。
(特にPキー以外の列を含む条件の場合)
なので、処理A・処理Bで同一行が複数対象になった場合
更新行がたすきがけになればデッドロックが発生します。
処理A・Bで絶対に同一行が更新対象になりませんか?
ロック・ユーザーIDが重なることはなさそうだけど・・・
どうしてもダメなら行ロックではなくテーブルロックにして
試してみてください。
ご回答ありがとうございます。
テーブルロックを試してみます。
ご回答に関しまして、1つ質問させていただいても
よろしいでしょうか?
>処理A・処理Bで同一行が複数対象になった場合
>更新行がたすきがけになればデッドロックが発生します。
処理A・処理Bとも、同一行への更新は無いのですが、
やはり、たすきがけ状態になり、
デッドロックが発生してしまうのでしょうか?
例)処理A実行時
行A・B・Cが更新対象行
処理B実行時
行X・Y・Zが更新対象行
よろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Oracle SQL update方法 2 2022/06/22 14:07
- MySQL UPDATE my_items SET item_name '赤い,甘い,ケーキ' WHERE id 1 2023/01/03 09:52
- Access(アクセス) アクセス テーブルの空白を変数に置換するボタンが作りたい 4 2022/07/08 11:19
- その他(データベース) 更新クエリをリンクデータベーステーブルに実行し実行時エラー3362固有インデックスに重複する値が含ま 1 2022/09/21 11:44
- Android(アンドロイド) Googleのファミリーリンクの危険性に気付いてしまったのですが、皆さんの感想を教えてください! 2 2023/05/09 10:01
- UNIX・Linux shellscript内のコマンドを、sudo(toor)として実行 2 2022/09/23 15:05
- au(KDDI) au設定のログイン出来なくなりました 1 2023/01/30 13:25
- iPad ワイモバイルのシンプルMプランのシェアプランのSIMが、ipadに使える設定方法を教えてください。 2 2023/08/16 11:34
- iPhone(アイフォーン) iPhoneで画面ロックのパスワード忘れました。フェイスIDで開てはいますがパスワードのロックを再設 2 2023/01/31 22:12
- docomo(ドコモ) SIMロック、またはSIMロック解除の仕組みをおしえてください。 5 2022/04/25 10:57
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
SQLのエラー(~付近に不適切な...
-
ACCESS2007 フォーム 「バリア...
-
【VB.NET】日付型の列にNULLを...
-
sqlserverで集計結果をUPDATEし...
-
【SQLサーバ】float型における...
-
SQLサーバー接続 特定のPCがWin...
-
BULK INSERT時のNull許容について
-
SQL ExpressエディションのCPU...
-
SQLをはじめから勉強するには
-
Visuaal Studio Community 2022...
-
SQLCMDにて教えていただきたい...
-
SQL文 複数実行
-
<SQL>重複しているデータの場合...
-
Microsoft SQL Serverについて
-
Wacom Cintiq 16 と Wacom Cint...
-
SQL クエリ データ数
-
SQL Server management studio ...
-
Tverは無料でしょうか?
-
サーバー破壊
-
Access2021 「ISNULL関数には引...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
SQLのエラー(~付近に不適切な...
-
ACCESS2007 フォーム 「バリア...
-
sqlserverで集計結果をUPDATEし...
-
【VB.NET】日付型の列にNULLを...
-
SQLサーバー接続 特定のPCがWin...
-
Accessの重複なしのカウントの...
-
SQL Date型の列から年月だけを...
-
sqlで、600行あるテーブルを100...
-
SQLサーバで和暦から西暦に変換...
-
BULK INSERT時のNull許容について
-
SQL文 複数実行
-
SQLCMDにて教えていただきたい...
-
【SQLサーバ】float型における...
-
<SQL>重複しているデータの場合...
-
chr(13) と char(13) の違いっ...
-
Visuaal Studio Community 2022...
-
[SQLServer] テーブル名からカ...
-
sqlserverで対象のレコードを削...
-
AccessのInsertクエリのあとつ...
-
sqlserverで同一キー単位で金額...
おすすめ情報