2009-02-23 155 views
5

我想设置SQL Server 2008警报以在任何过程执行1秒或更长时间(仅举例)时通知我。存储过程执行时间过长时的SQL警报

任何想法?

编辑:

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

回答

3

不,这里没有通知。 你必须设置一个跟踪并且随时进行轮询。

+0

你能给我多一点细节? – muerte 2009-02-23 15:41:59

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, 
     '[email protected]' 
+0

这将检查工作表现。我需要检查数据库(或整个服务器)中执行的每个存储过程。 – muerte 2009-02-23 15:38:26

0

您可以登录运行较慢的查询使用SQL事件探查器,但不会帮助你的警告,特别是。 (我想你可以登录到一个文件或数据库表,并有其他的东西“听”,并提出警报)。

如果你不熟悉SQL事件探查器这里的步骤:

您应该比服务器本身以外的东西上运行SQL事件探查器。

开始与SQLProfilerTSQL_Duration模板

设置过滤器:时间:1000(milliseonds)

在筛选器可以限制数据库,登录,或在必要时类似“大于”。

在可以限制只存储过程的事件(默认还包括SQL语句)

+0

是的,这是手动工作,不自动(没有警报)。 – muerte 2009-02-23 15:42:56

0

如果你是不是在找一个免费的解决方案,你可以看看SQL Sentry。它做你的要求和更多。

2

我想添加到Mladen Prajdic的正确答案,并改进来自SQL Server Central的kevchadders的回答。我在下面提出的解决方案使用DBMail代替SQLMail(通过xp_sendmail调用由SQLServerCentral的解决方案使用)。实质上,SQLMail使用MAPI,而且安装起来比较困难,DBMail使用SMTP并且更容易设置。这里的more information关于两者的区别。

我无法获得SQL Server Central的解决方案在SQL 2005中工作,下面的解决方案仅在我安装的基于版本的SQL 2005 - YMMV上进行了测试。

首先,你需要一个新的UDF,这将作业ID转换成进程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 

然后是存储过程:

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 

此存储过程可以可以轻松地安排为SQL Server代理作业或任何其他必需的方法。如果作业未运行或它在指定参数内运行,则不采取任何操作。如果作业运行时间超过指定时间,它会发送电子邮件。

例如

EXEC sp_check_job_running 'JobNameGoesHere', 5, '[email protected]' 

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

2

你可以使用监控软件像Nagios定期算在你的数据库查询速度慢的数量。

我个人使用以下查询与优秀PRTG。我将它设置为大于3秒内每次,或当最慢的查询超过10秒需要更长的时间我有超过5个查询与执行时间每次给我发电子邮件:

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的子串)