- PR -

SQLServerでのLOCKについて

1
投稿者投稿内容
未記入
会議室デビュー日: 2008/06/19
投稿数: 4
投稿日時: 2008-06-19 12:02
LOCKの動作についてお知恵をお貸しください。

実現したいことは以下の通りです。
1.テーブル全体に対して更新不可とするLOCKを行う。
2.レコードの参照は可能(ダーティリードは不可)

ロックは行えるのですが、
ロックしたテーブルを他のプロセスから二重にロックしてしまえるようなのです。


@あるプロセスからテーブルロック
SET LOCK_TIMEOUT 0

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO
BEGIN TRANSACTION
GO
select * from M001_USER WITH (TABLOCK, HOLDLOCK);

A別のプロセスから同様にロック
 @↑と同様のSQL実施

B先にロックしたプロセスで一件更新すると
 「ロックされています」旨のエラーメッセージ


先にテーブルロックしたプロセス以外からはロックさせず、
かつ、レコードの読み取りを可能にする方法はないのでしょうか?

普通に実現できそうなのですが、失敗してしまっています。
初歩的な問題ですみません。。
未記入
大ベテラン
会議室デビュー日: 2008/02/07
投稿数: 115
投稿日時: 2008-06-19 12:18
共有ロックになっているからですね。代わりに更新ロックを使用してください。

TABLOCK, UPDLOCK
未記入
会議室デビュー日: 2008/06/19
投稿数: 4
投稿日時: 2008-06-19 13:29
ありがとうございます。

この場合、共有でも排他でもなく、更新ロックが適切なのですね。

ただ、最初のプロセスでロックすると、
別のプロセスでSELECTで読み取れなくなってしまうのです。

@最初のプロセス
SET LOCK_TIMEOUT 0

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO
BEGIN TRANSACTION
GO
select * from M001_USER WITH (TABLOCK, UPDLOCK);

A別プロセスから
select * from M001_USER
→ロックタイムアウトの旨のエラーメッセージ


どうもロックレベルの問題ではないかもしれません。
SQLServerManagementStdioから検証しているのですが、
環境設定の問題でしょうか?

どなたかお分りになりませんでしょうか
未記入
会議室デビュー日: 2008/06/19
投稿数: 4
投稿日時: 2008-06-19 15:36
自己レスです。

SQLServer Management Studioには利用状況モニタがありまして、
ロックの状況が確認できました。
(なにも知らないことが情けない。。)

肝心のロックの状況ですが、
要求モードが'X'(排他モード)になっていました。

WITH(TABLOCK, UPDLOCK)とした場合は、
要求モードが'U'(更新モード)になって欲しい。

なぜだろうか?もう少し調べます。
未記入
会議室デビュー日: 2008/06/19
投稿数: 4
投稿日時: 2008-06-19 19:01
自己レスです。

WITH(UPDLOCK)とすることで目的にあったロックがかけられるようです。


SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
GO
select * from M001_USER WITH (UPDLOCK);

として状態を確認すると、
PAGEに対して'IU'
(おそらく)TABLEに対して'IX'
のロックがかかりました。

この状態で別プロセスから操作すると以下のようになりました。
SELECT → OK
SELECT WITH(UPDLOCK) → NG
UPDATE → NG
INSERT → NG


テーブルに対してロックをかけたいからTBLLOCKという訳ではないようです。
一括更新ロックを行いたい場合にTBLLOCKを指定する、と以下にありました。
(http://msdn.microsoft.com/ja-jp/library/ms175519.aspx)
一括更新ロック時は、一括読み込みに参加していない他のプロセスは、その間テーブルアクセスできません、とのことでした。


お騒がせ致しましたm(_ _)m


1

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