2015-08-18 12 views
4

的超時(原因爲什麼我需要以下是不重要的)強制特定的存儲過程在30秒後停止:我不想重新配置整個DB

我想怎麼辦將執行以下操作,以便執行通常需要30分鐘的存儲過程,但是在60秒的設置時間後程序將停止 - 實際上與運行該過程的SSMS相同,並在60之後按取消按鈕秒。

我不想重新配置整個數據庫,以便每個其他長時間運行的存儲過程在30秒後超時 - 只有特定過程TESTexecuteLongRunningProc

下面是測試過程被稱爲:

CREATE PROCEDURE [dbo].[TESTlongRunningProc] 
AS 
BEGIN 

    --placeholder that represents the long-running proc 
    WAITFOR DELAY '00:30:00'; 

END; 

這是我想調整,使之自行抵消60秒後的PROC:

​​
+0

這可能有所幫助:http://stackoverflow.com/a/1354333/673707 – Helio

+0

@Helio謝謝。我需要在tsql過程中執行此操作 - 是您發送給我的鏈接中的語法嗎? (我沒有看到它) – whytheq

+0

https://msdn.microsoft.com/en-us/library/ms189040.aspx – Helio

回答

2

從本質上講,你可以創建一個單獨的進程來觀看特定的任務和指標的背景和殺死如果必要。讓我們開始在你想跟蹤的代碼中植入一個跟蹤設備。我用了一個關鍵短語「殺死我」的評論塊。你可以把類似的東西在你原來的代碼

CREATE PROCEDURE TrackedToKill 
-- EXEC TrackedToKill 
/* Comment Block tracking device: Kill Me*/ 
AS 
BEGIN 
DECLARE @Counter bigint = 0 
WHILE 1 = 1 
BEGIN 
SET @Counter = @Counter + 1 
WAITFOR DELAY '00:00:30' 
END 
END 

然後讓我們看看我們是否能夠找到運行的會話

SELECT session_id, 
command,database_id,user_id, 
wait_type,wait_resource,wait_time, 
percent_complete,estimated_completion_time, 
total_elapsed_time,reads,writes,text 
FROM sys.dm_exec_requests 
CROSS APPLY sys.dm_exec_sql_text (sys.dm_exec_requests.sql_handle) 
WHERE text LIKE '%Kill Me%' 
AND session_id <> @@SPID 

OK大,這應該返回與您的跟蹤設備的會話。然後,我們可以將其轉換爲另一個存儲過程,該過程將根據跟蹤設備和您可能需要的任何其他標準來終止您的流程。您可以手動啓動,也可以在啓動時使用SQL代理啓動。包含儘可能多的附加條件,以確保限制你所殺的範圍(即:用戶,數據庫,數據塊,或尚未回滾的進程)。

CREATE PROCEDURE HunterKiller 
-- EXEC HunterKiller 
AS 
BEGIN 
DECLARE @SessionToKill int 
DECLARE @SQL nvarchar(3000) 
WHILE 1=1 
BEGIN 
SET @SessionToKill = (SELECT TOP 1 session_id 
    FROM sys.dm_exec_requests 
    CROSS APPLY sys.dm_exec_sql_text (sys.dm_exec_requests.sql_handle) 
    WHERE session_id <> @@SPID 
    AND text LIKE '%Kill Me%' 
    AND total_elapsed_time >= 15000) 
SET @SQL = 'KILL ' + CONVERT(nvarchar,@SessionToKill) 
EXEC (@SQL) 
WAITFOR DELAY '00:00:05' 
END 
END 
1

假設你可以使用SQL Server代理,也許使用sp_start_job和sp_stop_job過程可以爲你工作。

這是未經測試,沒有任何形式的擔保,且參數已經縮短了可讀性:

-- control procedure 


declare @starttime DATETIME = SYSDATETIME() 

exec msdb..sp_start_job 'Job' -- The job containing the target procedure that takes 30 minutes 

while 1>0 

    BEGIN 
     -- Check to see if the job is still running and if it has been running long enough 
     IF EXISTS(
         SELECT TOP 1 b.NAME 
         FROM msdb..sysjobactivity a 
         INNER JOIN msdb..sysjobs b 
           ON a.job_id = b.job_id 
         WHERE start_execution_date >= @starttime 
           AND stop_execution_date IS NULL 
           AND b.NAME in ('job') 
           and DATEDIFF(second,start_execution_date,SYSDATETIME()) >= 60 
       ) 
     BEGIN 

      exec msdb..sp_stop_job 'Job' 

     END 

    waitfor delay '00:00:05'; 

END