Comment get le nom d'index de sys.dm_tran_locks

Je travaille sur une solution multi-locataire. En tant que tel, nous avons beaucoup de bases de données sur notre server SQL. Je suis à la search d'un problème de locking et je dois pouvoir voir quels verrous sont en attente.

J'ai interrogé la vue dynamic sys.dm_tran_locks , mais j'aimerais également inclure les noms de database, d'object et d'index auxquels la colonne resource_associated_entity_id fait reference. Ce lien mène à la table sys.partitions , mais cette table ne renvoie que des lignes pour la database en cours et les verrous que je regarde sont répartis autour de plusieurs bases de données.

Est-il possible d'get cette information sans créer un slider et en utilisant des requêtes générées dynamicment?

Techniquement "non". Il n'y a aucune fonction de méta-données qui obtiendra des noms d'index en dehors du context de database actuel. Ce sortingste fait affecte également défavorablement l'utilisation de ce qui suit en essayant de les utiliser d'une manière aussi utile:

  • sys.dm_db_index_physical_stats
  • sys.dm_db_index_physical_stats
  • sys.dm_db_index_usage_stats

Donc vous avez deux options:

  • SQL dynamic (comme vous l'avez soupçonné)
  • Une fonction SQLCLR qui accepte tous les ID requirejs, y compris database_id , et se connecte via "context connection = true" pour interroger la vue système voulue (ce qui explique comment j'ai résolu ce problème en termes de noms d'index et de sys.objects dans SQL # , mais la technique de prendre en paramètre database_id tant que paramètre pour une fonction SQLCLR – Scalar ou TVF – et de la connecter localement via un SQL construit dynamicment à ladite database fonctionnerait de la même manière pour toutes les autres métadonnées).
    MODIFIER
    Pour le rendre encore plus facile, passez le nom de la database et concaténez-le dans le SqlCommand.CommandText et utilisez les ID comme SqlParameter . Donc, la signature serait, en termes d'get le nom de l'index:
    GetIndexName(@DatabaseName sysname, @object_id INT, @index_id INT)
    et utilisé comme suit:
    GetIndexName(DB_NAME(dmv.database_id), dmv.object_id, dmv.index_id)

Juste pour info, voici une list de fonctions de méta-données, groupées par si vous pouvez ou non spécifier la database ou sont actuelles-database seulement:

Peut spécifier la database

  • INDEX_COL (via un nom d'object qualifié complet)
  • OBJECT_ID (via un nom d'object qualifié complet)
  • OBJECT_NAME (via le paramètre database_id )
  • OBJECT_SCHEMA_NAME (via le paramètre database_id )

Current-Database-Only

  • INDEXPROPERTY
  • OBJECT_DEFINITION
  • OBJECTPROPERTY
  • OBJECTPROPERTYEX
  • SCHEMA_ID
  • SCHEMA_NAME
  • TYPE_ID
  • TYPE_NAME

Réponse courte: non, il n'y a aucun moyen d'éviter cela. sys.partitions et d'autres vues spécifiques à la database sont ennuyantes de cette façon. Pour les objects entiers, vous pouvez généralement contourner ceci avec OBJECT_NAME() , car cela prend un ID de database. Pour les ID d'allocation, vous n'avez pas de chance.

Techniquement parlant, vous pouvez éviter d'écrire des sliders vous-même en utilisant notre ancien pote sp_msforeachdb , mais puisque cela n'est pas documenté et ne donne généralement pas les résultats dans le format que vous voulez, écrire vous-même est une meilleure idée.

Parce que sys.dm_tran_locks est très dynamic, il ne sera pas facile d'get les informations de locking juste au moment où vous en avez besoin. Une alternative possible est d'utiliser une trace de profileur ou une session d'événement étendue pour get la séquence exacte des verrous acquis (évidemment, puisqu'il s'agit de tonnes de données, vous ne le feriez que lors du dépannage de requêtes spécifiques). Si tout ce dont vous avez besoin est de savoir qui tient les choses au moment où la merde proverbiale frappe le ventilateur, sp_msforeachdb 'dbcc opentran(''?'')' Est toujours étonnamment efficace.