我正在对 SQL Server 2014 执行以下 dmv 查询以查找服务器上的所有活动和任何阻塞活动:
SELECT Distinct
...
FROM sys.dm_exec_requests er
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st
LEFT JOIN sys.dm_exec_sessions ses ON ses.session_id = er.session_id
LEFT JOIN sys.dm_exec_connections con ON con.session_id = ses.session_id
WHERE st.text IS NOT NULL And DB_Name(er.database_id) IN ('Vincent', 'Vincent_Audit')
ORDER BY BlockingSessionId Desc, SessionId
Run Code Online (Sandbox Code Playgroud)
此查询的示例结果如下:
可以看到会话120被112阻塞,112被69阻塞。但是进程69并没有出现,因为它在sys.dm_exec_requests中不存在。
因此,以下查询不返回任何结果:
SELECT *
FROM sys.dm_exec_requests
Where session_id = 69
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么会这样?
我需要一个例程来有效识别哪些查询导致阻塞。这与我之前的问题如何找到仍然持有锁的查询有关?.
我知道网上有很多关于这方面的资料,但所有这些资料都是基于活动会话上的最后一条 SQL 语句很可能是获取锁的那个(因此产生了阻塞),这并不总是真的(在我的情况下,从来没有)。
我已将 设置blocking-process-threshold
为 30 秒并开始分析阻塞进程报告 (BPR)。
当达到阈值时,每次发生阻塞时都会触发这些报告。
它包含有关阻塞 spid 和阻塞 spid 的信息。
通常,阻塞 spid 会在获取并持有资源(表、页或行)锁的语句之后运行几个语句:因此,不管报告内容如何,我仍然不知道究竟是哪个查询导致了该阻塞。
通常 SQL Server DMV 只显示每个 的最后一个 SQL 文本session_id
,与活动锁(例如sys.dm_tran_locks
)相关的 DMV也没有解决这个问题。
调整阻塞的查询在这里不是最好的方法:我们的应用程序全部基于嵌入在客户端代码中的动态 SQL,我们不使用存储过程,并且基于我目前看到的阻塞,所有阻塞的查询都被正确索引并写成。
我认为解决这个问题的一个选项是收集候选查询,这可能会产生阻塞,然后使用在 BPR 上收集的时间戳和 spid 查找此信息。你同意?如果是这样,您能否指出一种使用 xEvents 以尽可能少的开销来做到这一点的方法?
performance sql-server transaction locking blocking performance-tuning