PIEBALDconsult Ответов: 1

Как определить, выполняется ли конкретная процедура в SQL server


Мы столкнулись с некоторыми проблемами при запуске заданий ETL (вручную и/или в отладке) во время выполнения задания интеграции. Поэтому меня попросили выяснить, как наши задания ETL определяют, является ли он "безопасным" для запуска.
Среди выдвинутых идей есть идея о том, что конечно система SQL Server знает, выполняется ли процедура интеграции, и мы можем запросить различные таблицы и представления, которые предоставляются.
Быстрый поиск выдал многообещающий запрос, но он оказался ненадежным-он дает много ложных отрицательных результатов, т. е. он не обнаруживает, что процедура выполняется, даже если это так. Многие (но не все) ложные негативы связаны с тем, что процесс находится в подвешенном состоянии, а иногда он восстанавливает статистику и тому подобное.

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

Я призываю великих гуру SQL Server среди нас:
У кого здесь есть надежный запрос для определения того, что конкретная процедура выполняется в SQL Server (в частности, 2014).

Что я уже пробовал:

Запрос, который я нашел (на другом сайте), в основном таков:

SELECT *
FROM [sys].[dm_exec_requests] A
CROSS APPLY [sys].[dm_exec_sql_text] ( A.[sql_handle] ) B
WHERE B.[objectid] = OBJECT_ID ( '[dbo].[uspJobControl]' )


Я тоже попробовал это сделать:

SELECT *
FROM [sys].[dm_exec_cached_plans] A
CROSS APPLY [sys].[dm_exec_sql_text] ( A.[plan_handle] ) B
WHERE B.[objectid] = OBJECT_ID ( '[dbo].[uspJobControl]' )


Что, по крайней мере, дает ложные положительные результаты, а не ложные отрицательные.

И для полноты картины я также объединил эти два понятия:

SELECT *
FROM [sys].[dm_exec_cached_plans] A
CROSS APPLY [sys].[dm_exec_sql_text] ( A.[plan_handle] ) B
LEFT OUTER JOIN [sys].[dm_exec_requests] C
ON A.[plan_handle] = C.[plan_handle]
WHERE B.[objectid] = OBJECT_ID ( '[dbo].[uspJobControl]' )


Что, конечно, дает ложные негативы.

[no name]

SQL profiler даст вам правильный статус для мониторинга состояния экземпляра SQL, но иногда он немного ухудшит производительность..

Maciej Los

Кажется, sp_help_job (Transact-SQL) | Microsoft Docs[^ это то, что вы ищете...

PIEBALDconsult

Нет, это касается только заданий агента SQL Server, а не процессов на сервере, которые могут выполняться через SSMS, SSIS, SQLCMD, ADO.net-неважно.

Maciej Los

ОК

1 Ответов

Рейтинг:
2

Wendelius

Не уверен, правильно ли я понял ваш вопрос, но вы пытаетесь выяснить, выполняется ли процедура для того, чтобы предотвратить запуск чего-то другого (возможно, той же процедуры), верно?

Если это проблема, то я не думаю, что проверка того, что что-то находится в исполнении, является правильным способом. Проверка показывает вам ситуацию только в тот момент, когда проверка выполняется. Через несколько миллисекунд ситуация может измениться.

Если вы пытаетесь предотвратить параллельное выполнение, то не используйте маленькую таблицу с одной строкой. Первый обновляет таблицу в транзакции, оставляя исключительную блокировку строки, и когда другой процесс пытается выполнить то же обновление, он приостанавливается до тех пор, пока блокировка не будет снята.

Конечно, существует несколько способов предотвращения одновременных операций, но этот довольно прост.

ДОПОЛНЕНИЕ:
---------
Я думаю, что одна из главных проблем заключается в том, что dm_exec_requests показывает, что происходит сейчас. Если процедура вызывает другие процедуры, то в системном представлении может отображаться другая процедура, чем ожидалось. Он показывает не самое внешнее название процедуры, а самое внутреннее.

Я сделал небольшой тест следующим образом, первые две процедуры

create procedure FindMeToo as
declare @i int;
begin
  while 1=1 begin
     set @i = 1;
     -- This is going to take awhile
  end;
end;
go

create procedure FindMe as
declare @i int;
begin
  while 1=1 begin
     exec FindMeToo
  end;
end;
go
Тогда если я позвоню в FindMe который из них я хотел бы знать, работает он или нет
declare @i int
while 1=1 begin
  set @i=1
  exec FindMe
end
go
Теперь я спрашиваю себя, что происходит с
SELECT *
FROM [sys].[dm_exec_requests] A
CROSS APPLY [sys].[dm_exec_sql_text] ( A.[sql_handle] ) B

Я получаю скандал, где objectid является 711673583 Если я спрошу, что это такое
select * from sysobjects where id =711673583
Я получаю
name      id        xtype uid
--------- --------- ----- ---
FindMeToo 711673583 P     1

Так что казнь уже началась FindMeToo даже не смотря на FindMe вот с чего началась эта история.

Что касается планов на будущее, я бы туда не заглядывал. Если сервер работает хорошо и у вас есть достаточный объем памяти, план для большинства операторов находится в кэше, работает он или нет.

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

Я бы все же рекомендовал рассмотреть "блокирующий замок" -подход, если вы хотите предотвратить запуск процедуры во время выполнения другой операции. Насколько я могу судить, это было бы надежно и легко реализовать.


PIEBALDconsult

Я надеялся, что у тебя есть ответ.
И да, и нет. Это очень длительная процедура (часы), а не вопрос миллисекунд.
Не заботясь о параллельном выполнении процедуры интеграции, обеспокоенный ETL усекает таблицу, которую интеграция пытается прочитать.
У нас есть журнал всех процессов в системе, который должен быть достаточно хорошим индикатором того, что интеграция запущена, и это моя рекомендация, но мы также хотим быть уверены, что исследуем эту возможность.

Wendelius

Это сложный, но интересный вопрос. Пожалуйста, смотрите измененный ответ.

PIEBALDconsult

Очень вероятно, что это невозможно сделать таким образом, поэтому я ожидаю использовать другую технику.