Advertisement
Lars-UT

Email Alert for Long Running Queries

Jul 10th, 2013
323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
T-SQL 8.59 KB | None | 0 0
  1. /* SPROC - Return Query Text for queries that have been running greater than a specfied time.sql
  2. Purpose: Alert for Long Running Queries
  3. Author: Lars Rasmussen
  4. Last Edited: 2013-07-10
  5. Instructions: Use in Job that runs every 2 minutes, Pass milliseconds as Threshold
  6. References:
  7.     Query Result in HTML format http://coding.smashingmagazine.com/2008/08/13/top-10-css-table-designs/
  8.     CSS prettiness for table output http://coding.smashingmagazine.com/2008/08/13/top-10-css-table-designs/
  9.  
  10.     Example of Running Stored Proc with 5 min threshold for currently running queries:
  11.     EXEC sp_Check_For_Long_Running_Queries 300000
  12. */
  13.  
  14. CREATE PROCEDURE [dbo].[usp_Check_For_Long_Running_Queries]
  15.     -- Add the parameters for the stored procedure here
  16.     @intMillisecondsDurationExceeded INT = 10000 --(in ms) default value longer than 10 secs
  17. AS
  18. BEGIN
  19. SET NOCOUNT ON;
  20. --Return Query Text for queries that have been running > specfied time
  21. DECLARE @RowCount INT = 0,
  22.         @TotalNumLongRunningQueries INT = 0
  23.        
  24. SELECT   D.text SQLStatement,
  25.          A.Session_ID SPID,
  26.          ISNULL(B.status, A.status) Status,
  27.          DATEDIFF(minute, A.last_request_start_time, getdate()) AS MinutesRun,
  28.          A.login_name Login,
  29.          A.host_name HostName,
  30.          C.BlkBy,
  31.          DB_NAME(B.Database_ID) DBName,
  32.          B.command,
  33.          ISNULL(B.cpu_time, A.cpu_time) CPUTime,
  34.          ISNULL(( B.reads + B.writes ), ( A.reads + A.writes )) DiskIO,
  35.          A.last_request_start_time LastBatch,
  36.          A.program_name
  37. INTO #TempLongRunningQueriesForAlerts
  38. FROM     sys.dm_exec_sessions A
  39.          LEFT JOIN sys.dm_exec_requests B
  40.             ON A.session_id = B.session_id
  41.                AND B.total_elapsed_time > @intMillisecondsDurationExceeded
  42.          LEFT JOIN (
  43.                      SELECT   A.request_session_id SPID,
  44.                               B.blocking_session_id BlkBy
  45.                      FROM     sys.dm_tran_locks AS A
  46.                               INNER JOIN sys.dm_os_waiting_tasks AS B
  47.                                  ON A.lock_owner_address = B.resource_address
  48.                    ) C
  49.             ON A.Session_ID = C.SPID
  50.          CROSS APPLY sys.dm_exec_sql_text(sql_handle) D
  51. WHERE    A.is_user_process = 1
  52.          AND A.Session_ID != @@SPID
  53.          AND ISNULL(B.status, A.status) != 'sleeping'
  54.          AND B.command NOT LIKE 'BACKUP DATABASE%'
  55.          AND B.command NOT LIKE 'RESTORE HEADER%'
  56.          AND B.command NOT LIKE 'UPDATE STATISTIC'
  57.          --AND D.text NOT LIKE 'ALTER INDEX%'
  58.          AND A.program_name NOT LIKE 'DatabaseMail - DatabaseMail - Id%';
  59. SELECT @TotalNumLongRunningQueries = COUNT (*) FROM #TempLongRunningQueriesForAlerts;
  60.  
  61. SELECT   SQLStatement,
  62.          SPID,
  63.          Status,
  64.          MinutesRun,
  65.          Login,
  66.          HostName,
  67.          BlkBy,
  68.          DBName,
  69.          command,
  70.          CPUTime,
  71.          DiskIO,
  72.          LastBatch,
  73.          program_name FROM #TempLongRunningQueriesForAlerts;
  74.  SELECT @RowCount = COUNT(1) FROM #TempLongRunningQueriesForAlerts
  75.  IF @RowCount > 0
  76.     BEGIN
  77.         PRINT 'Doing stuff...'
  78.                             DECLARE @HTMLBody VARCHAR(MAX),
  79.                               @TableHead VARCHAR(MAX),
  80.                               @TableStyle VARCHAR(MAX),
  81.                               @TableTail VARCHAR(MAX)
  82.  
  83.                             SET @TableTail = '</table>';
  84.                             SELECT @TableHead = '<html><head>' + '<style>'
  85.                               --+ 'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
  86.                               +'#hor-minimalist-b{font-family:"Lucida Sans Unicode", "Lucida Grande", Sans-Serif;font-size:11px;background:#fff;width:90%;border-collapse:collapse;text-align:left;}#hor-minimalist-b th{font-size:14px;font-weight:normal;color:#039;border-bottom:2px solid #6678b1;padding:10px 8px;}#hor-minimalist-b td{border-bottom:1px solid #ccc;color:#669;padding:4px 6px;vertical-align: top;}#hor-minimalist-b tbody tr:hover td{color:#009;}'
  87.                               --+'#hor-minimalist-b{font-family:"Lucida Sans Unicode", "Lucida Grande", Sans-Serif;font-size:12px;background:#fff;width:90%;border-collapse:collapse;text-align:left;margin:10px;}#hor-minimalist-b th{font-size:14px;font-weight:normal;color:#039;border-bottom:2px solid #6678b1;padding:10px 8px;}#hor-minimalist-b td{border-bottom:1px solid #ccc;color:#669;padding:6px 8px;vertical-align: top;}#hor-minimalist-b tbody tr:hover td{color:#009;}'
  88.                               --+ '</style>' + '</head>' + '<body><table id="hor-minimalist-b">'
  89.                               + '</style>' + '</head>' + '<body style="font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace;font-size:12px;background:#fff">'
  90.                               + '<table id="hor-minimalist-b">'
  91.                               + '<tr bgcolor=#FFEFD8><td align=left>' + LTRIM(RTRIM (CAST(@TotalNumLongRunningQueries AS CHAR(4)) + '&nbsp;row(s)' )) + '</td>'
  92.                               --+ '<tr bgcolor=#FFEFD8><td valign=top>' + LTRIM(RTRIM (CAST(@TotalNumLongRunningQueries AS CHAR(4)) )) + '</td>'
  93.                               + '<td align=left>SQLStatement</td>'
  94.                               + '<td align=left>SPID</td>'
  95.                               + '<td align=center>Status</td>'
  96.                               + '<td align=left>MinutesRun</td>'
  97.                               + '<td align=center>Login</td>'
  98.                               + '<td align=center>HostName</td>'
  99.                               + '<td align=left>BlkBy</td>'
  100.                               + '<td align=center>DBName</td>'
  101.                               + '<td align=center>command</td>'
  102.                               + '<td align=left>CPUTime</td>'
  103.                               + '<td align=left>DiskIO</td>'
  104.                               + '<td align=left>LastBatch</td>'
  105.                               + '<td align=center>program_name</td></tr>';
  106.  
  107.                             SELECT  @HTMLBody = (
  108.                                                   SELECT ROW_NUMBER() OVER ( ORDER BY LastBatch DESC ) AS [TD],
  109.                                                          ISNULL(SQLStatement, 'NULL') AS [TD],
  110.                                                          SPID AS [TD],
  111.                                                          Status AS [TD],
  112.                                                          MinutesRun AS [TD],
  113.                                                          Login AS [TD],
  114.                                                          HostName AS [TD],
  115.                                                          ISNULL(BlkBy, 0) AS [TD],
  116.                                                          ISNULL(DBName, 'NULL') AS [TD],
  117.                                                          ISNULL(command, 'NULL') AS [TD],
  118.                                                          CPUTime AS [TD],
  119.                                                          DiskIO AS [TD],
  120.                                                          LastBatch AS [TD],
  121.                                                          ISNULL(program_name, 'NULL') AS [TD]
  122.                                                   FROM   #TempLongRunningQueriesForAlerts
  123.                                                   ORDER BY LastBatch DESC
  124.                                                 FOR
  125.                                                   XML RAW('tr'),
  126.                                                       ELEMENTS
  127.                                                 )
  128.      
  129.                            
  130.                             DECLARE @server_footer NVARCHAR(2000);
  131.                             SELECT @server_footer =
  132.                             '<br>' + '<br>' + '<br>' +
  133.                             + '<hr style="border: 1px dashed #ccc;" />'
  134.                             + 'Server Time: ' + CONVERT(CHAR(19), GETDATE(), 120)
  135.                             + '<br>SQL Server instance ' + @@SERVERNAME + ' (' + CAST(SERVERPROPERTY('productversion') AS VARCHAR) + ' - ' + SUBSTRING(@@VERSION, CHARINDEX('X',@@VERSION),4) + ' - ' + CAST(SERVERPROPERTY('edition') AS VARCHAR)  
  136.                             + '<hr style="border: 1px dashed #ccc;" />'
  137.                             + '</p></body></html>'
  138.  
  139.                             IF @HTMLBody IS NULL
  140.                               OR @HTMLBody = ''
  141.                               SET @HTMLBody = '<tr><td colspan="4">no data found</td></tr>'
  142.  
  143.                             SELECT  @HTMLBody = @TableHead + @HTMLBody + @TableTail + @server_footer;
  144.                             --SELECT  @HTMLBody = @TableHead + @HTMLBody + @TableTail;
  145.                              EXEC msdb.dbo.sp_send_dbmail
  146.                                    @recipients = '[email protected]',
  147.                                    --@copy_recipients = '[email protected]',
  148.                                    @body = @HTMLBody,
  149.                                    @subject = 'Long Running Query Detected',
  150.                                    @profile_name = 'YOUR_DBMAIL_PROFILE',
  151.                                    @body_format = 'html';
  152.      END
  153.    
  154. ELSE
  155.      BEGIN
  156.         RETURN(0)
  157.      END
  158.  
  159. DROP TABLE #TempLongRunningQueriesForAlerts;
  160.  
  161. SET NOCOUNT OFF;
  162. END
  163. ;;
  164. GO
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement