代码之家  ›  专栏  ›  技术社区  ›  markom

存储过程执行时间过长时的SQL警报

  •  5
  • markom  · 技术社区  · 16 年前

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

    有什么想法吗?

    编辑:

    好吧,看来这是不可能的。但是,我只想告诉您另一个方向,我知道主数据库中有一些统计表,其中包含编译计数、调用数和其他各种统计数据。我是否可以定期询问他们,然后以某种方式报告?

    6 回复  |  直到 15 年前
        1
  •  3
  •   Mladen Prajdic    16 年前

    不,没有关于此的通知。

        2
  •  2
  •   Paul Prewett    13 年前

    我想补充一下Mladen Prajdic的正确答案,并从SQL Server Central改进kevchadders的答案。下面我建议的解决方案使用DBMail而不是SQLMail(SQLServerCentral的解决方案通过xp\u sendmail调用使用SQLMail)。从本质上讲,SQLMail使用MAPI并且更难设置,DBMail使用SMTP并且更容易设置。这是 more information 关于两者之间的区别。

    我无法让SQLServerCentral的解决方案在SQLS2005中工作,下面的解决方案仅在我安装的基于版本的SQLServer2005-YMMV上进行了测试。

    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
    

    例如

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

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

        3
  •  2
  •   Thomas    12 年前

    长时间运行作业的警报过程 http://www.sqlservercentral.com/scripts/Lock+and+Connection+Management/30144/

    如果您无法访问,请输入下面的文本。

    对于定期运行且运行时间较短的作业,DBA可能希望知道作业何时运行的时间过长。在这种情况下,仅仅检查作业是否正在运行是不行的;需要能够确保它不会长时间运行。将作业id与sysprocesss中的进程id进行匹配需要对作业id进行一些重新安排以进行匹配。此脚本创建一个存储过程,该过程将接受作业名称、允许的最大运行时间和要通知的电子邮件地址。然后,它将使用作业名称重新设置作业编号的字符串,并检查sysprocesss(基于作为程序名称一部分的进程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'
    
        4
  •  2
  •   Community    7 年前

    你可以使用像这样的监控软件 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 st.text )

        5
  •  0
  •   Kristen    16 年前

    您可以使用SQL事件探查器记录运行缓慢的查询,但这并不能帮助您发出警报。(我想您可以登录到一个文件或数据库表,然后让其他东西“侦听”并发出警报)。

    如果您不熟悉SQL Profiler,请执行以下步骤:

    您应该在服务器本身以外的其他设备上运行SQL Profiler。

    从SQLProfilerTSQL_持续时间模板开始

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

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

    在事件中,您可以仅限制存储过程(默认值还包括SQL语句)

        6
  •  0
  •   Tim Cooper    12 年前

    如果你不是在寻找一个免费的解决方案,你可以看看 SQL Sentry . 它会满足你的要求,甚至更多。