SQL Server で取得されているロック数を把握する際には、sys.dm_tran_locks を参照することが多いかと思います。
ロック数が数 10 万 / 数 100 万となっている環境では、この DMV を参照して COUNT(*) をするだけでも数分かかってしまい、定期的にロック数を取得して推移を把握するということが難しいケースがあります。
この DMV を使用せず、類似のロック数を把握することができるかを検証してみました。
パフォーマンスモニターからロック情報を取得
DMV からの情報取得が難しい場合、パフォーマンスモニターから情報を取得するのが定番になります。
ロックについてのパフォーマンスモニターの情報については次の情報が使用できます。
「1.」はロックに特化したカウンターとなり、取得されたロックの情報を取得することはできるのですが、現在取得されているロック数の合計までは取得することはできません。
そのため、え取得されたロックが保持されているものなのか、瞬間的なものなのかの判断ができません。
「2.」はメモリについてのカウンターとなり、この中にはロック用のメモリの情報も含まれています。今回使用するのは次の項目となります。
-
Lock Memory (KB): ロック用に確保されているメモリサイズ
-
Lock Blocks Allocated: ロック用のメモリに何ブロック割り当てられているか
-
Lock Blocks: 使用中のロックブロックの数
ロック用のメモリはキャッシュされ、再利用されます。
「Lock Memory (KB)」「Lock Blocks Allocated」については、キャッシュされている領域の情報となるため、これらの値は「現在使用中のロック数」を示すものではありません。
「Lock Blocks」が現在使用中のロックブロック数を示し、この値が sys.dm_tran_locks の件数相当の値となっていそうです。
試しに、次のようなクエリで「5,000,000」のロックを取得した状態にしてみます。
SET TRANSACTION ISOLATION LEVEL SNAPSHOT; IF @@TRANCOUNT > 0 ROLLBACK TRAN DECLARE @cnt bigint BEGIN TRAN SELECT TOP 5000000 * FROM LINEITEM WITH (INDEX=0, ROWLOCK, HOLDLOCK) SELECT @cnt = COUNT(*) FROM sys.dm_tran_locks PRINT @cnt --ROLLBACK TRAN
今回の環境では「5,046,459」のロックが取得された状態となります。
この状態で取得したパフォーマンスモニターの情報が次の画像となります。
「Lock Blocks」は「5,046,269」となり、sys.dm_tran_locks の件数相当となっていました。
SQL Server の Memory Manager オブジェクト には次のように記載されています。
サーバーで使用中のロック ブロックの現在数 (定期的に更新されます) を指定します。 ロック ブロックは、テーブル、ページ、行など、ロックされている個々のリソースを表します。
リアルタイム性はなく、ロック数に大きな動きがないと値が更新されないような挙動をしていました。
しかし、DMV からの情報より低負荷でじ、情報を取得することができますので、現在取得されているロック数のおおよその値を取得したい場合には、この値を活用できるのではないでしょうか。