Sql-Server-2012
檢測 SQL Server 中鎖定的表或行
我正在嘗試了解/學習如何追踪被阻止會話的詳細資訊。
所以我創建了以下設置:
create table foo (id integer not null primary key, some_data varchar(20)); insert into foo values (1, 'foo'); commit;
現在我從兩個不同的客戶端連接到數據庫兩次。
第一屆會議問題:
begin transaction update foo set some_data = 'update' where id = 1;
為了保留鎖,我明確地不在那裡送出。
在第二個會話中,我發出相同的語句,當然,由於鎖定而等待。現在我正在嘗試使用不同的查詢來查看會話 2 正在等待
foo
表。
sp_who2
顯示以下內容(我刪除了一些列以僅顯示重要資訊):SPID | 狀態 | BlkBy | 數據庫名稱 | 命令 | SPID | 請求ID -----+--------------+-------+----------+------------------+------+---------- 52 | 睡覺| . | 食物b | 等待命令 | 52 | 0 53 | 睡覺| . | 食物b | 等待命令 | 53 | 0 54 | 暫停 | 52 | 食物b | 更新 | 54 | 0 56 | 可執行 | . | 食物b | 選擇進入 | 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 | 等待類型 | 資源地址 | 資源描述 -----------+-----------+--------------------+--------------------------------------------------------------------------------- 54 | LCK_M_X | 0x000000002a35cd40 | 鑰匙鎖 hobtid=72057594046054400 dbid=6 id=lock4ed1dd780 mode=X associatedObjectId=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
即使我們啟用了快照隔離和讀取送出的快照,該語句也會被阻止。下一步是弄清楚選擇被阻止的原因(我認為如果啟用快照隔離就不可能)。作為第一步,我想了解該會話正在等待什麼。
我認為這可以滿足您的需求。
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
你可以試試看 :
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