MSSQL

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

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)