我正在尝试了解/了解如何跟踪被阻止会话的详细信息.
所以我创建了以下设置:
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 | Status | BlkBy | DBName | Command | SPID | REQUESTID -----+--------------+-------+----------+------------------+------+---------- 52 | sleeping | . | foodb | AWAITING COMMAND | 52 | 0 53 | sleeping | . | foodb | AWAITING COMMAND | 53 | 0 54 | SUSPENDED | 52 | foodb | UPDATE | 54 | 0 56 | RUNNABLE | . | 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 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实际上不包含我正在寻找的信息.
所以我要找的是一个返回类似的查询:
“session 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