存储过程执行时间过长的SQL Alert

时间:2009-02-23 10:59:08

标签: sql-server sql-server-2008 monitoring notifications alert

我想设置一个SQL Server 2008警报,以便在任何过程执行1秒或更长时间时通知我(仅作为示例)。

有什么想法吗?

编辑:

好的,似乎这是不可能的。但是,只是为了向另一个方向推动你,我知道master数据库中有统计表,它们包含编译计数,调用次数和其他各种统计信息。我可以定期查询它们,然后以某种方式报告它吗?

6 个答案:

答案 0 :(得分:3)

没有没有通知。 你必须设置一个跟踪并不时地轮询它。

答案 1 :(得分:2)

如果在sqlservercentral上找到它(可能是旧版本的SQL Server,但仍可能与2008相关)

长期工作的警报程序 http://www.sqlservercentral.com/scripts/Lock+and+Connection+Management/30144/

如果您无法访问它,请在下方显示。

对于定期运行且运行时间很短的作业,DBA可能想知道作业何时运行时间过长。在这种情况下,只需检查以查看作业是否正在运行;需要确保它没有长时间运行的能力。将作业ID与sysprocesses中的进程ID匹配需要重新安排作业ID以进行匹配。此脚本创建一个存储过程,该过程将接受作业名称,允许的最长运行时间和要通知的电子邮件地址。然后,它将使用作业名称重新编写作业编号并检查sysprocesses(基于进程ID是程序名称的一部分)以确定作业运行的时间,然后警告该时间是否超过了“允许时间”参数。

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'

答案 2 :(得分:2)

我想补充一下Mladen Prajdic的正确答案,并改进来自SQL Server Central的kevchadders答案。我在下面提出的解决方案使用DBMail而不是SQLMail(SQLServerCentral的解决方案通过xp_sendmail调用使用它)。本质上,SQLMail使用MAPI并且更难设置,DBMail使用SMTP并且更容易设置。这是关于两者之间差异的more information

我无法让SQL Server Central的解决方案在SQL 2005中运行,并且下面的解决方案仅在我安装的SQL 2005 - YMMV基于版本的测试中进行了测试。

首先,您需要一个新的UDF,它会将作业ID转换为JOIN的进程ID:

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代理作业或任何其他必需的方法。如果作业未运行或在指定参数内运行,则不执行任何操作。如果作业运行时间超过指定值,它会发送电子邮件。

e.g。

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

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

答案 3 :(得分:2)

您可以使用Nagios等监控软件定期计算数据库中慢查询的数量。

我个人使用以下查询与优秀的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并调整{{1}上的SUBSTRING })

答案 4 :(得分:0)

您可以使用SQL事件探查器记录运行缓慢的查询,但这对您的警报没有帮助,具体而言。 (我想您可以登录到文件或数据库表,并有其他“监听”并发出警报)。

如果您不熟悉SQL事件探查器,请执行以下步骤:

您应该在服务器本身以外的其他位置运行SQL事件探查器。

从SQLProfilerTSQL_Duration模板开始

将过滤器:持续时间:“大于”设置为1000(毫秒)

在过滤器中,您可以根据需要限制数据库,登录或类似内容。

在事件中,您可以限制为仅仅SProcs(默认还包括SQL语句)

答案 5 :(得分:0)

如果您不想寻找免费解决方案,可以查看SQL Sentry。它可以满足您的要求和更多。