2014-10-20 4 views
1

Я работаю над многопользовательским решением. Таким образом, у нас есть много баз данных на нашем SQL Server. Я смотрю на проблему блокировки и должен уметь видеть, какие блокировки ждут.Как получить имя индекса из sys.dm_tran_locks

Я запросил динамический вид sys.dm_tran_locks, но хотел бы также включить имена объектов, объектов и индексов, на которые ссылается столбец resource_associated_entity_id. Это связано с таблицей sys.partitions, но эта таблица возвращает строки только для текущей базы данных, а блокировки, которые я просматриваю, распределены по нескольким базам данных.

Есть ли способ получить эту информацию без создания курсора и использования динамически сгенерированных запросов?

+0

Мартин: Я просто заметил, что я забыл поставить в использование для передачи в DatabaseName. Я понимаю, что вы уже отметили это как принятое, но все равно обновляетесь, чтобы быть ясным о том, что я имел в виду, чтобы сделать его действительно легким :-) –

ответ

2

Технически «нет». Нет функции метаданных, которая будет получать имена индексов за пределами текущего контекста базы данных. Этот печальный факт также негативно сказывается на использовании следующее при попытке использовать их в такой же полезным образом:

Так у вас есть два варианта:

  • Динамический SQL (как вы подозревали)
  • Функция SQLCLR, которая принимает все необходимые идентификаторы, включая database_id, и подключается через «context connection = true» для запроса предполагаемого системного представления (именно так я решил эту проблему в терминах имен индексов и sys.objects в SQL# , но метод принятия в database_id в качестве параметра функции SQLCLR - Scalar или TVF - и локального подключения через динамически построенный SQL к указанной базе данных будет работать одинаково для любых других метаданных).
    EDIT
    Чтобы сделать это еще проще, передать имя базы данных и конкатенации, что в SqlCommand.CommandText и использовать идентификаторы, как SqlParameter с.Таким образом, подпись была бы, с точки зрения получения имя индекса:
    GetIndexName(@DatabaseName sysname, @object_id INT, @index_id INT)
    и используется следующим образом:
    GetIndexName(DB_NAME(dmv.database_id), dmv.object_id, dmv.index_id)

Просто FYI, вот список функций мета-данных, сгруппированных по ли вы не можете указать базу данных или тока базы данных только:

можно указывать базы данных

Current-Database -Only

2

Короткий ответ: нет, нет способа избежать этого. sys.partitions и другие виды базы данных раздражают этот путь. Для целых объектов вы обычно можете обойти это с помощью OBJECT_NAME(), так как это принимает идентификатор базы данных. Для идентификаторов размещения вам не повезло.

С технической точки зрения, вы можете избежать написания курсоров самостоятельно, используя наш старый приятель sp_msforeachdb, но так как это не документировано и, как правило, не дает результатов в формате, который вы хотите, в любом случае, писать его сам по себе является лучшей идеей.

Поскольку sys.dm_tran_locks отличается высокой динамичностью, будет легко получить информацию о блокировке только в тот момент, когда она вам понадобится. Возможной альтернативой является использование трассировки профилировщика или расширенного сеанса событий для получения точной последовательности захваченных замков (очевидно, поскольку это множество данных, вы делаете это только при устранении неполадок с конкретными запросами). Если вам нужно только знать, кто держит вещи в то время, когда пресловутое дерьмо попадает в вентилятор, sp_msforeachdb 'dbcc opentran(''?'')' все еще на удивление эффективен.