在SQL Server中检测锁定的表或行


20

我正在尝试了解/学习如何跟踪被阻止会话的详细信息。

因此,我创建了以下设置:

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 | DBName | 指令| SPID | 要求
----- + -------------- + ------- + ---------- + ---------- -------- + ------ + ----------
52 | 睡觉 。| foodb | 等待命令| 52 | 0        
53 | 睡觉 。| foodb | 等待命令| 53 | 0        
54 | 已暂停| 52 | foodb | 更新| 54 | 0        
56 | 可运行 。| foodb | 选择进入| 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 | 键锁hobtid = 72057594046054400 dbid = 6 id = lock4ed1dd780模式= X relatedObjectId = 72057594046054400

同样,这是预期的。

我的问题是,我不知道如何找到会话54正在等待的实际对象名称。

我发现,要加入一些查询sys.dm_tran_lockssys.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 2014年

我无法重新创建您在SQL Server 2012中看到的问题。我创建了一个测试数据库,启用了RCSI,创建了表,并运行了两个update语句,并且看到上一个查询返回的行。
Max Vernon

如果您想要视觉帮助来检测锁,则可以使用一种称为SQL锁查找器的开源工具。您可以在以下网址找到源代码:github.com/LucBos/SqlLockFinder或在以下网址下载可执行文件:sqllockfinder.com我们也喜欢您可以对代码做出的任何贡献,以便我们对其进行改进。
Luc Bos

Answers:


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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.