SQL Serverでロックされたテーブルまたは行を検出する


20

ブロックされたセッションの詳細を追跡する方法を理解/学習しようとしています。

そこで、次のセットアップを作成しました。

create table foo (id integer not null primary key, some_data varchar(20));
insert into foo values (1, 'foo');
commit;

次に、2つの異なるクライアントからデータベースに2回接続します。

最初のセッションの問題:

begin transaction
update foo set some_data = 'update'
  where id = 1;

ロックを保持するために、明示的にコミットしません

2番目のセッションでは、同じステートメントを発行します。もちろん、ロックのために待機します。セッション2がfooテーブルを待機していることを確認するために、さまざまなクエリを使用しようとしています。

sp_who2 以下を示します(重要な情報のみを表示するためにいくつかの列を削除しました)。

SPID | ステータス| BlkBy | DBName | コマンド| SPID | リクエストID
----- + -------------- + ------- + ---------- + ---------- -------- + ------ + ----------
52 | 寝る| 。| foodb | 待機中のコマンド| 52 | 0        
53 | 寝る| 。| foodb | 待機中のコマンド| 53 | 0        
54 | 一時停止| 52 | foodb | 更新| 54 | 0        
56 | 実行可能| 。| foodb | SELECT INTO | 56 | 0        

これは予想されることであり、セッション54はセッション52からのコミットされていない変更によってブロックされます。

クエリsys.dm_os_waiting_tasksもこれを示しています。声明:

select session_id, wait_type, resource_address, resource_description
from sys.dm_os_waiting_tasks
where blocking_session_id is not null;

戻り値:

session_id | wait_type | resource_address | resource_description                                                            
----------- + ----------- + -------------------- + ----- -------------------------------------------------- --------------------------
        54 | LCK_M_X | 0x000000002a35cd40 | keylock hobtid = 72057594046054400 dbid = 6 id = lock4ed1dd780 mode = X relatedObjectId = 72057594046054400

再びこれが予想されます。

私の問題は、セッション54が待機している実際のオブジェクト名を見つける方法がわからないことです。

私は次のような参加sys.dm_tran_locksしているクエリをいくつか見つけましたsys.dm_os_waiting_tasks

SELECT ....
FROM sys.dm_tran_locks AS l
  JOIN sys.dm_os_waiting_tasks AS wt ON wt.resource_address = l.lock_owner_address

しかし、上記のテストシナリオでは、この結合は何も返しません。そのため、その結合が間違っているかdm_tran_locks、実際に探している情報が含まれていません。

したがって、私が探しているのは、
セッション54はテーブルのロックを待機していますfoo」のようなものを返すクエリです。


いくつかの背景情報:

私が解決しようとしている現実の問題はもう少し複雑ですが、「どのテーブルでセッション54が待機しているのか」という質問に要約されます。問題の問題には、複数のテーブルを更新する大規模なストアドプロシージャと、それらのテーブルの一部にアクセスするビューからの選択が関係しています。select声明は、私たちがスナップショット分離を持っていると、コミットのスナップショットが有効になって読んでいてもブロックされています。選択がブロックされる理由を理解する(スナップショット分離が有効になっている場合は不可能だと思った)ことが次のステップになります。

最初のステップとして、そのセッションがを待っているかを知りたいです。



@MaxVernon:それを確認してくれてありがとう。しかし、それから私はさらに混乱しています。ロックおよびブロックされたセッションがあることわかっているのに、何も返されないのはなぜですか?
a_horse_with_no_name 14年

SQL Server 2012で発生している問題を再現できません。テストデータベースを作成し、RCSIを有効にし、テーブルを作成し、両方の更新ステートメントを実行しました。最後のクエリで返された行が表示されます。
マックスヴァーノン14年

ロックの検出に視覚的な支援が必要な場合は、SQLロックファインダーと呼ばれるオープンソースツールを利用できます。あなたは上のソースを見つけることができます:github.com/LucBos/SqlLockFinderまたは上の実行可能ファイルをダウンロードしてください:sqllockfinder.com我々はまた、我々はそれを改善することができますので、あなたがコードに作ることができる任意の貢献を愛します。
リュックボス

回答:


23

私はこれがあなたが必要とすることを行うと思います。

USE 'yourDB'
GO
SELECT  
    OBJECT_NAME(p.[object_id]) BlockedObject
FROM    sys.dm_exec_connections AS blocking
    INNER JOIN sys.dm_exec_requests blocked
        ON blocking.session_id = blocked.blocking_session_id
    INNER JOIN sys.dm_os_waiting_tasks waitstats
        ON waitstats.session_id = blocked.session_id
    INNER JOIN sys.partitions p ON SUBSTRING(resource_description, 
        PATINDEX('%associatedObjectId%', resource_description) + 19, 
        LEN(resource_description)) = p.partition_id

3

あなたはそれを試すことができます :

SELECT 
db_name(rsc_dbid) AS 'DATABASE_NAME',
case rsc_type when 1 then 'null'
              when 2 then 'DATABASE' 
              WHEN 3 THEN 'FILE'
              WHEN 4 THEN 'INDEX'
              WHEN 5 THEN 'TABLE'
              WHEN 6 THEN 'PAGE'
              WHEN 7 THEN 'KEY'
              WHEN 8 THEN 'EXTEND'
              WHEN 9 THEN 'RID ( ROW ID)'
              WHEN 10 THEN 'APPLICATION' end  AS 'REQUEST_TYPE',

CASE req_ownertype WHEN 1 THEN 'TRANSACTION'
                   WHEN 2 THEN 'CURSOR'
                   WHEN 3 THEN 'SESSION'
                   WHEN 4 THEN 'ExSESSION' END AS 'REQUEST_OWNERTYPE',

OBJECT_NAME(rsc_objid ,rsc_dbid) AS 'OBJECT_NAME', 
PROCESS.HOSTNAME , 
PROCESS.program_name , 
PROCESS.nt_domain , 
PROCESS.nt_username , 
PROCESS.program_name ,
SQLTEXT.text 
FROM sys.syslockinfo LOCK JOIN 
     sys.sysprocesses PROCESS
  ON LOCK.req_spid = PROCESS.spid
CROSS APPLY sys.dm_exec_sql_text(PROCESS.SQL_HANDLE) SQLTEXT
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.