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

a_h*_*ame 20 sql-server-2012 locking

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

所以我创建了以下设置:

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

现在我从两个不同的客户端连接到数据库两次。

第一届会议议题:

begin transaction
update foo set some_data = 'update'
  where id = 1;
Run Code Online (Sandbox Code Playgroud)

我明确没有在那里提交以保持锁定。

在第二个会话中,我发布了相同的声明,当然,由于锁定而等待。现在我正在尝试使用不同的查询来查看会话 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;
Run Code Online (Sandbox Code Playgroud)

返回:

session_id | 等待类型 | 资源地址| 资源描述                                                            
-----------+-----------+------------+----- -------------------------------------------------- --------------------------
        54 | LCK_M_X | 0x000000002a35cd40 | keylock hobtid=72057594046054400 dbid=6 id=lock4ed1dd780 模式=X 关联对象ID=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
Run Code Online (Sandbox Code Playgroud)

但是在我上面的测试场景中,这个 join 不会返回任何东西。所以要么加入是错误的,要么dm_tran_locks实际上不包含我正在寻找的信息。

所以我正在寻找的是一个查询,它返回如下内容:
会话 54 正在等待表中的锁foo”。


一些背景资料:

我试图解决的现实生活问题有点复杂,但归结为“会话 54 在哪个桌子上等待”的问题。有问题的问题涉及更新多个表的大型存储过程以及从访问其中一些表的视图中进行选择。select即使我们启用了快照隔离和读取提交的快照,该语句也会被阻止。弄清楚为什么选择被阻止(我认为如果启用快照隔离是不可能的)将是下一步。

作为第一步,我想了解该会话正在等待什么

Jam*_*son 24

我认为这可以满足您的需求。

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
Run Code Online (Sandbox Code Playgroud)