1

我正在研究多租户解决方案。因此,我们的 SQL Server 上有很多数据库。我正在查看一个锁定问题,并且需要能够查看正在等待哪些锁。

我查询了sys.dm_tran_locks动态视图,但还想包括 resource_associated_entity_id 列引用的数据库、对象和索引名称。这链接到sys.partitions表,但该表仅返回当前数据库的行,而我正在查看的锁分布在多个数据库中。

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

4

2 回答 2

2

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

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

因为sys.dm_tran_locks是高度动态的,所以在需要的时候获取锁定信息并不容易。一种可能的替代方法是使用分析器跟踪或扩展事件会话来获取获取的锁的确切顺序(显然,由于这是大量数据,您只会在对特定查询进行故障排除时这样做)。如果你只需要知道当众所周知的狗屎击中粉丝时谁在阻止事情,那么sp_msforeachdb 'dbcc opentran(''?'')'它仍然非常有效。

于 2014-10-20T16:08:03.067 回答
2

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

所以你有两个选择:

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

仅供参考,这里是元数据函数列表,按您是否可以指定数据库或仅当前数据库分组:

可以指定数据库

仅当前数据库

于 2014-10-20T16:08:39.237 回答