如何从sys.dm_tran_locks获取索引名称

时间:2014-10-20 15:32:37

标签: sql-server tsql dynamic-management-views

我正致力于多租户解决方案。因此,我们的SQL Server上有很多数据库。我正在查看锁定问题,需要能够看到正在等待哪些锁。

我查询了sys.dm_tran_locks动态视图,但是还希望包含resource_associated_entity_id列引用的数据库,对象和索引名称。这链接到sys.partitions表,但该表只返回当前数据库的行,而我查看的锁分布在几个数据库周围。

有没有办法在不创建游标和使用动态生成的查询的情况下获取此信息?

2 个答案:

答案 0 :(得分:2)

简短回答:不,没有办法避免这种情况。 sys.partitions和其他特定于数据库的视图很烦人。对于整个对象,通常可以使用OBJECT_NAME()解决此问题,因为它需要数据库ID。对于分配ID,您运气不好。

从技术上讲,您可以避免使用我们的旧朋友sp_msforeachdb来自己编写游标,但由于没有记录,并且通常不会以您想要的格式提供结果,所以写作它本身就是一个更好的主意。

由于sys.dm_tran_locks具有高度动态性,因此在您需要时很容易获得锁定信息。一种可能的替代方法是使用分析器跟踪或扩展事件会话来获取所获取的确切锁序列(显然,由于这是大量数据,因此您只能在对特定查询进行故障排除时执行此操作)。如果你需要的只是知道当时众所周知的事情会让粉丝罢了,sp_msforeachdb 'dbcc opentran(''?'')'仍然会令人惊讶地有效。

答案 1 :(得分:2)

技术上“不”。没有元数据函数可以获取当前数据库上下文之外的索引名称。当尝试以类似有用的方式使用它们时,这个令人遗憾的事实也会对使用以下内容产生不利影响:

所以你有两个选择:

  • 动态SQL(正如您所怀疑的那样)
  • 一个SQLCLR函数,它接受所有必需的ID,包括database_id,并通过“context connection = true”连接以查询预期的系统视图(这就是我在索引名称和sys方面解决了这个问题的方法SQL#中的.objects,但是将database_id作为参数接收到SQLCLR函数 - 标量或TVF - 并通过动态构建的SQL本地连接到所述数据库的技术也可以使用对于任何其他元数据) 的修改
    为了使其更加简单,请传入数据库名称并将其连接到SqlCommand.CommandText并将ID用作SqlParameter。所以签名就是获得索引名称:
    GetIndexName(@DatabaseName sysname, @object_id INT, @index_id INT)
    用法如下:
    GetIndexName(DB_NAME(dmv.database_id), dmv.object_id, dmv.index_id)

仅供参考,以下是元数据功能列表,按您是否可以指定数据库或仅限当前数据库进行分组:

可以指定数据库

当前-数据库 - 仅