@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

SQL Server 2000におけるロック モード および デッドロック時の動作について

1
投稿者投稿内容
sin
会議室デビュー日: 2006/08/14
投稿数: 14
投稿日時: 2008-12-15 22:45
いつもお世話になっております。

現在、Visual Studio .NET、SQL Server 2000を用いて開発を行っております。

本番環境にて、ロックによる登録不具合が発生しております。
データ更新時、行単位の共有ロックを取得し、更新を行ないます。
この際、通常であればページ単位(PAG)にインテント更新(IU)がかかります。

ですが、不具合発生時にはページ単位(PAG)に共有インテント更新(SIU)がかかっています。(ユーザA)

そのため、他のユーザ(ユーザB)が行単位の更新ロックを取得し(ここまでは出来る)
実際に更新を行い排他ロックに変換する際に、
ページ単位のロックはインテント排他(IX)に変換されようとします。
その際に、ユーザAの共有インテント更新ロックと競合し、
ブロックされていると思われます。

ページ単位に共有ロック(もしくは共有インテント更新)がかかる状況というのは何が考えられますでしょうか。





もう一点、上記現象が発生した際、
(ユーザBがブロック中)
共有インテント更新を保持しているユーザAが、
同じデータを参照(SELECT)しようとすると、
ユーザBがインテント排他を取得しようとしているためか、
参照できずにデッドロックになっていると思われます。

その際に、ユーザAのプロセスが殺されて、ユーザBは正常に
登録できるのですが、
ユーザAが、
この際、try catchでexceptionエラーを取得しようとしているのですが
catchに飛ばずに自分のプロセスが殺されたことを取得できず、
try内の以降の処理を継続してしまいます。

そのため、BEGINしていたトランザクションも無効となり、
その後のエラーでロールバックしようとしても
既にコミットされてしまい、不正データが出来てしまっている状況です。

プロセスが殺されたことを、
「トランザクション (プロセス ID XXX) が、lock リソースでほかのプロセスとデッドロックしました。トランザクションがデッドロックの対象として選択されています。トランザクションを再実行してください。」
で取得できるはずだと考えていたのですが
(現に上記エラーが発生しているログを取得済みです。
 発生時状況は定かではないですが)
取得する方法はありませんでしょうか。


sin
会議室デビュー日: 2006/08/14
投稿数: 14
投稿日時: 2008-12-15 22:46
>データ更新時、行単位の共有ロックを取得し、更新を行ないます。
上記は更新ロックの間違いでした。
sin
会議室デビュー日: 2006/08/14
投稿数: 14
投稿日時: 2008-12-26 13:21
本件に関してですが、
二点目の、デッドロックがtry catchで取得できない件については
解決いたしました。

http://support.microsoft.com/kb/316667/ja

投稿させていただいた内容が説明不足で申し訳ございませんでした。
エラーが取得できないのはSELECT時(sqldatareader)でした。

上記のURLの通り、SQL Server側のバグであったようです。
SELECT時の際のデッドロックの情報は返されない(ことがある)とのことでした。
nextresultを行うことで、正常であれば問題なく処理が出来、
異常(デッドロックが発生しているのにcatch出来ていなかった)の場合は、
そこでエラーであることが判断出来るようです。

一点目に関しては解決しておりませんので、
なにかご存知の方がいらっしゃいましたらよろしくお願い致します。

めだか
大ベテラン
会議室デビュー日: 2004/11/11
投稿数: 109
投稿日時: 2008-12-26 14:52
インデックスをはずしてやってみるとか・・・
1

スキルアップ/キャリアアップ(JOB@IT)