QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

SQLServerのTABLOCKについて

SQLServerのTABLOCKについて質問させていただきます。

SQLのテーブル排他は (TABLOCK, XLOCK)で実現できると考えていますが、期待通りに動いてくれません。
お手数ですがこのような動作になる理由を教えていただけないでしょうか。

[実行したスクリプト]
Management Studioで3つのクエリエディタを立ち上げて、それぞれで以下の3行を実行する。

begin tran
select * from TestTable with (TABLOCK, XLOCK)
rollback

[実行手順]
1)一つ目のエディタでselectまでを実行
---->> selectの結果が表示される
2)二つめのエディタでselectまでを実行
---->> ロックで待たされる
3)三つめのエディタでselectまでを実行
---->> ロックで待たされる
4)一つ目のエディタでrollbackを実行
---->> 二つめのエディタでselectの結果が表示される
---->> 三つめのエディタでエラーが表示される

[エラーメッセージ内容]
メッセージ 1205、レベル 13、状態 18、行 4
トランザクション (プロセス ID 68) が、ロック 個のリソースで他のプロセスとデッドロックして、
このトランザクションがそのデッドロックの対象となりました。トランザクションを再実行してください。

[質問したいこと1]
どうして(4)の手順でデッドロックが発生するのでしょうか。
三つ目のエディタではロックがかかり続ける事を私は期待しています。

質問したいこと2 を (TABLOCKX)に変えると、期待した動作になります。
(TABLOCK, XLOCK) の機能はHOLDLOCKを除いた内容で(TABLOCKX)の機能と同等だとMSDNから読み取っていたので
理由が分かりません。
この2つの指定方法はどういった点で動作が変わるのでしょうか。

[実行環境]
OS:win2000 server
DB:SQLserver2005

質問者:DELI

回答

確かにそのように動作するみたいですね。

んで、実際にどのようにロックされているのか見てみるのが確実だと思います。
「現在の利用状況」でしたっけ?自宅には環境がないのでうろ覚えですが、
Management Studioにそのような項目があり、別ウィンドウでロックの状況を
確認することができます。

3の場合までいったときに、(TABLOCK, XLOCK)と(TABLOCKX)とで明らかに違う
挙動が読み取れます。
・(TABLOCK, XLOCK)
1個目のトランザクションは当然X(排他)
2個目と3個目はS(共有)申請中で、排他ロックの空き待ち。

・(TABLOCKX)
1個目のトランザクションは当然X(排他)
2個目と3個目はX(排他)申請中で、排他ロックの空き待ち。

この状況から多分こうだろうな、と言う想像ですが。

・1個目のトランザクションがロールバックされ、排他ロックが解除される。
・2個目のトランザクションの共有ロックが実施される
・3個目のトランザクションの共有ロックが実施される
・2個目のトランザクションの排他ロックが申請される(空き待ち)
・3個目のトランザクションの排他ロックが申請される(空き待ち)

という現象が発生し、典型的なデッドロックになってるんじゃないでしょうか。
つまりXLOCKは、読み取りであれば共有ロックをかけるTABLOCKの挙動を
最初から排他ロックかけるように変えるものではないってことですね。
あくまで別々に評価・実行されてる感じ。
(ちなみに記述する順番変えても同じでした)

MSDNライブラリなりにきちんと言及されているものを見つけたわけではないので、
できればちゃんとしたドキュメントで確認したいところですけれども。

投稿者:OakBow

編集 履歴 (0)

あ、ちなみに分離レベルはREAD COMMITEDです。デフォルト。
これは関係ないかなあ。。
[ メッセージ編集済み 編集者: OakBow 編集日時 2008-01-31 00:46 ]

投稿者:OakBow

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。