Posted at

特定のテーブルがロックされているか確認する。

More than 3 years have passed since last update.

SQL Serverにおいては、ロックの有無を確認するだけならsys.dm_tran_locksシステムビューですぐに確認できる。

sql

SELECT * FROM sys.dm_tran_locks

しかし、sys.dm_tran_locksではテーブルロックや行ロックなどの情報がまとめて提供され、ロックされている対象もオブジェクトIDでの表記になるため非常にわかりにくい。

表題のとおり、特定テーブルのロック状況を取得するならば、IDから名称を取得する関数などを利用するのがよいだろう。

具体的には以下のとおり。

 SELECT *

FROM sys.dm_tran_locks
WHERE resource_associated_entity_id
=(SELECT TOP 1 object_id FROM sys.partitions WHERE OBJECT_NAME(object_id)='TABLE-NAME');

ただし、サーバがビジーだったりテーブルロックがかかった状態では、sys.partitionsにロックがかかり応答が遅くなる。

先にresource_associated_entity_idを取得しておき、マジックワードとして直書きするのが、最終的には一番スマートになると思う。


自分がロックしたものを分別したい

sys.dm_tran_locksシステムビューのrequest_session_idカラムに、ロック取得セッションのセッションIDが入っている。

自分のセッションIDは以下のSQL文で確認できる。

sql

Select @@spid;



よって、自分がロックしたものかどうか判断してロックの有無を判定するSQL文は以下のようになる。

 SELECT COUNT(*)

FROM sys.dm_tran_locks
WHERE
(resource_associated_entity_id
=(SELECT TOP 1 object_id FROM sys.partitions WHERE OBJECT_NAME(object_id)='TABLE-NAME'))
and (request_session_id!=(Select @@SPID));


ロックが解除されるまで待機したい

SQL文の実行待機はWAITFORが利用できる。WHILE文を利用して以下のように出来なくもないが、プログラムで組んだほうが色々融通がきくと思います。

sql

WHILE

(SELECT COUNT(*) FROM sys.dm_tran_locks WHERE resource_associated_entity_id=(SELECT TOP 1 object_id FROM sys.partitions WHERE OBJECT_NAME(object_id)='TABLE-NAME')) != 0

BEGIN

WAITFOR DELAY '00:01'

END

SELECT TOP 1 * FROM TABLE-NAME WITH(TABLOCK,XLOCK)