从 sys.dm_tran_locks 中进行选择需要 100+ 毫秒

mwi*_*ahl 4 sql-server dmv sql-server-2017 query-performance

我们的应用程序使用 SQL Server 应用程序锁,并且在某些情况下我们需要查看给定的锁是否存在。为此,我们从 中检索和过滤信息sys.dm_tran_locks

这是可行的,但即使是SELECT * FROM sys.dm_tran_locks我们系统中针对此 DMV 的最简单查询 ( ) 也需要超过 100 毫秒(CPU 和持续时间),有时可能会超过 500 毫秒。这是无论是否以超级管理员用户身份运行、是否从 SSMS 运行时的情况。

full 最多返回大约 10,000 行SELECT,并且我们在具有充足 CPU 和 RAM 以及快速磁盘子系统的 VM 上运行。这个查询似乎不应该花费这么长时间。

有人以前见过这个或者知道这里可能发生什么吗?如果有帮助的话,我很乐意提供更多信息。

Pau*_*ite 10

您应该使用APPLOCK_MODEAPPLOCK_TEST而不是扫描 DMV 锁。

背景

DMVsys.dm_tran_locks本身采用广泛使用的流式表值函数 (sTVF) 接口,该接口通过使用仅限内部OPENROWSET(TABLE ...语法的 T-SQL 公开。该接口包含用于所有执行引擎迭代器的常用OpenGetRow和方法。Close

流式表值函数执行计划

许多系统功能和视图都使用 sTVF 模式。每个方法如何初始化以及提供对底层数据的一次一行访问的方式根据数据源的不同而有所不同。

下面是这个特定 DMV 的一些示例调用堆栈:

打开
打开

获取行
获得行

描述锁拥有者
描述锁的所有者

逻辑稳定性锁
逻辑稳定锁

洛克雷斯1
锁定资源

洛克雷斯2
关联对象 ID

列类型信息
输出列数据类型

提供给 sTVF 的参数(如果有的话)可以下推到内部数据访问中,也存在一些变化。在支持下推的情况下,行在显示到查询处理器之前会被过滤。

大多数 sTVF 支持将参数作为外部引用传递(例如,由 提供的列值APPLY),但并非全部。在几个主要产品版本中,对这方面的支持已经逐渐完善。

文档总结得很好:

由于sys.dm_tran_locks是从内部锁管理器数据结构填充的,因此维护此信息不会给常规处理增加额外的开销。

实现视图确实需要访问锁管理器内部数据结构。这可能会对服务器中的常规处理产生轻微影响。这些影响应该是不明显的,并且只影响大量使用的资源。

由于此视图中的数据对应于实时锁管理器状态,因此数据可以随时更改,并且随着获取和释放锁而添加和删除行。

由于保护锁管理器结构完整性的性质,查询此视图的应用程序可能会遇到不可预测的性能。

此视图没有任何历史信息。