有效识别阻塞查询的框架

tan*_*lle 4 performance sql-server transaction locking blocking performance-tuning

我需要一个例程来有效识别哪些查询导致阻塞。这与我之前的问题如何找到仍然持有锁的查询有关?.

我知道网上有很多关于这方面的资料,但所有这些资料都是基于活动会话上的最后一条 SQL 语句很可能是获取锁的那个(因此产生了阻塞),这并不总是真的(在我的情况下,从来没有)。

我已将 设置blocking-process-threshold为 30 秒并开始分析阻塞进程报告 (BPR)。
当达到阈值时,每次发生阻塞时都会触发这些报告。
它包含有关阻塞 spid 和阻塞 spid 的信息。

业务流程再造示例

通常,阻塞 spid 会在获取并持有资源(表、页或行)锁的语句之后运行几个语句:因此,不管报告内容如何,​​我仍然不知道究竟是哪个查询导致了该阻塞。

通常 SQL Server DMV 只显示每个 的最后一个 SQL 文本session_id,与活动锁(例如sys.dm_tran_locks)相关的 DMV也没有解决这个问题。

调整阻塞的查询在这里不是最好的方法:我们的应用程序全部基于嵌入在客户端代码中的动态 SQL,我们不使用存储过程,并且基于我目前看到的阻塞,所有阻塞的查询都被正确索引并写成。

我认为解决这个问题的一个选项是收集候选查询,这可能会产生阻塞,然后使用在 BPR 上收集的时间戳和 spid 查找此信息。你同意?如果是这样,您能否指出一种使用 xEvents 以尽可能少的开销来做到这一点的方法?

Han*_*non 6

我建议使用 XEvents 会话寻找长时间运行的会话。

您所描述的问题听起来像是您的客户端代码正在执行逐行(RBAR)处理,而不是使用高效的基于集合的方法。

设计不佳的客户端应用程序可能会执行以下操作:

  1. 连接到 SQL Server 以获取需要处理的项目列表。查询结果保持打开状态,直到处理完所有行。
  2. 在每一行上执行一些长时间运行的过程。
  3. 关闭查询。

什么应该发生的情况是:

  1. 连接到 SQL Server
  2. 运行查询,在本地缓存查询结果,然后关闭连接。
  3. 在不保持原始查询打开的情况下对每一行运行长时间运行的进程,从而防止阻塞。

可以使用快照隔离行版本控制来实现 SQL Server 的解决方法。有关详细信息,请参阅此 Technet 文档。本质上,行版本控制允许作者不阻塞读者,大大减少阻塞。