Оповещение SQL, когда хранимая процедура выполняется слишком долго

StackOverflow https://stackoverflow.com/questions/577233

Вопрос

Я хотел бы настроить оповещение SQL Server 2008, чтобы оно уведомляло меня, когда какая-либо процедура выполняется в течение 1 секунды или дольше (просто пример).

Есть какие-нибудь идеи?

Редактировать:

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

Это было полезно?

Решение

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

Другие советы

Я хотел бы добавить к правильному ответу Младена Прайдича и улучшить ответ kevchadders из SQL Server Central.Решение, которое я предлагаю ниже, использует DBMail вместо SQLMail (которое используется решением SQLServerCentral посредством вызова xp_sendmail).По сути, SQLMail использует MAPI и его сложнее настроить, а DBMail использует SMTP и его проще настроить.Вот дополнительная информация о разнице между этими двумя.

Я не смог заставить решение SQL Server Central работать в SQL 2005, и приведенное ниже решение было протестировано только при моей установке SQL 2005 - YMMV в зависимости от версии.

Во-первых, вам понадобится новый UDF, который преобразует идентификатор задания в идентификатор процесса для ОБЪЕДИНЕНИЯ:

CREATE FUNCTION dbo.udf_SysJobs_GetProcessid(@job_id uniqueidentifier)
RETURNS VARCHAR(8)
AS
BEGIN
    RETURN (substring(left(@job_id,8),7,2) +
    substring(left(@job_id,8),5,2) +
    substring(left(@job_id,8),3,2) +
    substring(left(@job_id,8),1,2))
END

И затем sproc:

CREATE PROC sp_check_job_running 
    @job_name char(50),
    @minutes_allowed int, 
    @person_to_notify varchar(50) 

AS 

DECLARE @minutes_running int, 
    @message_text varchar(255)

SELECT @minutes_running = isnull(DATEDIFF(mi, p.last_batch, getdate()), 0)
FROM master..sysprocesses p
JOIN msdb..sysjobs j ON dbo.udf_sysjobs_getprocessid(j.job_id) = substring(p.program_name,32,8)
WHERE j.name = @job_name

IF @minutes_running > @minutes_allowed 
    BEGIN
      SELECT @message_text = ('Job ' + UPPER(SUBSTRING(@job_name,1,LEN(@job_name))) + ' has been running for ' + SUBSTRING(CAST(@minutes_running AS char(5)),1,LEN(CAST(@minutes_running AS char(5)))) + ' minutes, which is over the allowed run time of ' + SUBSTRING(CAST(@minutes_allowed AS char(5)),1,LEN(CAST(@minutes_allowed AS char(5)))) + ' minutes.') 
      EXEC msdb.dbo.sp_send_dbmail
        @recipients = @person_to_notify,
        @body = @message_text,
        @subject = 'Long-Running Job to Check' 
    END

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

например ,

EXEC sp_check_job_running 'JobNameGoesHere', 5, 'admin@mycompany.com'

ХТ: http://www.sqlserverspecialists.co.uk/blog/_archives/2008/11/26/3996346.html

Если нашел это на sqlservercentral (вероятно, это для более старой версии SQL Server, но все еще может иметь отношение к 2008 году)

Процедура оповещения для Длительно выполняющегося задания http://www.sqlservercentral.com/scripts/Lock+and+Connection+Management/30144/

Текст ниже, если вы не можете получить к нему доступ.

Для заданий, которые выполняются периодически и должны занимать совсем немного времени, администратор базы данных может захотеть узнать, когда задание выполнялось слишком долго.В этом случае простая проверка ТОГО, запущено ЛИ задание, не поможет;необходима возможность убедиться, что он не работал в течение длительного периода.Сопоставление идентификатора задания с идентификатором процесса в системных процессах требует некоторой перестановки идентификатора задания для достижения соответствия.Этот скрипт создает хранимую процедуру, которая примет имя задания, максимально допустимое время выполнения и адрес электронной почты для уведомления.Затем он будет использовать имя задания для изменения номера задания и проверки системных процессов (на основе идентификатора процесса, являющегося частью названия программы), чтобы определить количество времени, в течение которого выполнялось задание, а затем предупреждать, если это время превышает параметр "разрешенное время".

CREATE proc sp_check_job_running
    @job_name       char(50),
    @minutes_allowed    int,
    @person_to_notify   varchar(50)
AS  

DECLARE @var1           char(1),
    @process_id     char(8),
    @job_id_char        char(8),
    @minutes_running    int,
    @message_text       varchar(255)

select @job_id_char = substring(CAST(job_id AS char(50)),1,8) 
from  msdb..sysjobs
where name = @job_name

select @process_id =    substring(@job_id_char,7,2) + 
            substring(@job_id_char,5,2) +
            substring(@job_id_char,3,2) +
            substring(@job_id_char,1,2)


select @minutes_running = DATEDIFF(minute,last_batch, getdate())
from master..sysprocesses
where program_name LIKE ('%0x' + @process_id +'%')

if @minutes_running > @minutes_allowed
  BEGIN
    select @message_text = ('Job ' 
    + UPPER(SUBSTRING(@job_name,1,LEN(@job_name)))
    + ' has been running for '
    + SUBSTRING(CAST(@minutes_running AS char(5)),1,LEN(CAST(@minutes_running AS char(5))))
    + ' minutes, which is over the allowed run time of '
    + SUBSTRING(CAST(@minutes_allowed AS char(5)),1,LEN(CAST(@minutes_allowed AS char(5)))) 
    + ' minutes.')
    EXEC master..xp_sendmail 
    @recipients = @person_to_notify, 
    @message = @message_text,
        @subject = 'Long-Running Job to Check'
  END

--  Typical job step syntax for job to do the checking

execute sp_check_job_running
      'JobThatSHouldBeDoneIn5Minutes', 
       5, 
       'DBAdmin@mycompany.com'

Вы могли бы использовать программное обеспечение для мониторинга, такое как Нагиос периодически подсчитывать количество медленных запросов в вашей базе данных.

Я лично использую следующий запрос с отличным PRTG.Я настроил его так, чтобы он отправлял мне электронное письмо каждый раз, когда у меня более 5 запросов со временем выполнения более 3 секунд каждый или когда самый медленный запрос занимает больше 10 секунд:

SELECT total_elapsed_time / execution_count / 1000000 avg_elapsed_time, execution_count, creation_time, last_execution_time, 
SUBSTRING(st.text, (qs.statement_start_offset/2) + 1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
WHERE total_elapsed_time / execution_count / 1000000 >= 3  -- filter queries that takes > 3 seconds
AND CHARINDEX('dm_exec_query_stats', st.text) = 0   -- In case this query is slow, we don't want it in the result set!
ORDER BY total_elapsed_time / execution_count DESC;

Отказ от ответственности:этот запрос основан на https://stackoverflow.com/a/820252/638040

Теперь, если вы хотите отслеживать свои Хранимые процедуры, то просто используйте sys.dm_exec_procedure_stats вместо того , чтобы sys.dm_exec_sql_text (также удалите это поле creation_time из выделенного и настройте ПОДСТРОКУ на st.text)

Вы можете регистрировать медленно выполняющиеся запросы с помощью SQL Profiler, но это не поможет вам, в частности, с предупреждением.(Я полагаю, вы могли бы войти в файл или таблицу базы данных, а что-то еще "прослушать" и выдать предупреждение).

На случай, если вы не знакомы с SQL Profiler, вот шаги:

Вы должны запустить SQL Profiler на чем-то другом, кроме самого сервера.

Начните с шаблона SQLProfilerTSQL_Duration

Установите фильтр :Продолжительность :"Больше" до 1000 (миллисекунды)

В фильтрах вы можете ограничить базу данных, логин или что-то подобное, если это необходимо.

В событиях вы можете ограничиться только SProcs (по умолчанию также включены инструкции SQL)

Если вы не ищете бесплатное решение, вы могли бы взглянуть на SQL - часовой.Он делает то, о чем вы просите, и даже больше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top