2011-05-02 53 views
9

我目前正在使用這樣的代碼來檢測SQL服務器作業是否正在運行。 (這是SQL Server 2005,所有SP的)如何準確檢測SQL Server作業是否正在運行並處理已在運行的作業?

return (select isnull( 
(select top 1 CASE 
    WHEN current_execution_status = 4 THEN 0 
    ELSE 1 
    END 
from openquery(devtestvm, 'EXEC msdb.dbo.sp_help_job') 
where current_execution_status = 4 and 
    name = 'WQCheckQueueJob' + cast(@Index as varchar(10)) 
), 1) 
) 

那裏沒有問題,一般來說,它工作得很好。

但是....(總是但是)

有時,我會調用此,得到​​的回覆是「作業未運行」的結果,在這一點上,我會嘗試,並開始工作,通過

exec msdb.dbo.sp_start_job @JobName 

和SQL將返回「的SQLAgent拒絕開始工作,因爲它已經有一個懸而未決的要求」。

確定。也沒有問題。可以想象,在這個代碼可以啓動之前,有一個目標作業可以開始的小窗口,但在檢查它是否已經啓動之後。但是,我可以把它包裝起來,只是忽略錯誤,對吧?

begin try 
if dbo.WQIsQueueJobActive(@index) = 0 begin 
    exec msdb.dbo.sp_start_job @JobName 
    break 
end   
end try begin catch 
    -- nothing here 
end catch 

雖然是這樣的問題。

9次了10年,這工作得很好。 SQL代理會引發錯誤,它會被捕獲,並且處理會繼續進行,因爲作業已經在運行,不會造成任何損壞。

但是偶爾,我會在Job History視圖中看到一條消息(請記住上面的代碼來檢測某個特定的作業是否正在運行,如果沒有從另一個作業運行,則啓動它)說該作業失敗因爲「SQLAgent已拒絕啓動該作業,因爲它已經有待處理的請求」。

當然,這是嘗試捕捉精確的錯誤應該被處理!

如果發生這種情況,執行工作剛剛去世,但不會立即從我可以告訴,只是八九不離十。我已經把記錄放在了地方,沒有一致性。有一次它失敗了,它會在a地點,下一次在地點b。在某些情況下,場所A和場所B只有一個

select @var = 'message' 

在它們之間。很奇怪。基本上,這項工作似乎被毫不客氣地拋棄,任何留在工作中執行的東西都根本沒有被執行。但是,如果我刪除了「exec StartJob」(或者只是調用一次,當我知道目標作業不能運行時),那麼所有的工作都可以正常運行,並且我在作業中的所有處理都會通過。

這一切背後的目的是爲了有一份工作開始作爲觸發的結果(除其他事項外),並且,如果作業已經啓動,真的沒有必要「再次啓動」。

有誰碰到與SQL代理的作業處理這樣的行爲?

編輯: 電流控制的流程是,像這樣:

  1. 更改表中(更新或插入)...
  2. 火災引發這就要求...
  3. 這...
  4. 開始具體工作,這一個存儲過程調用哪個...
  5. sp_Start_Job ...
  6. 調用另一個存儲過程(稱爲CheckQueue),這...
  7. 執行一些處理和...
  8. 檢查幾個表,並根據其內容可能......另一份工作
  9. 調用sp_start_job啓動第二個,同時工作 來處理額外的工作(這第二份工作,調用存儲過程CheckQueue也 但兩個調用操作上的數據完全獨立的套)
+0

不是我真正尋找的答案,但作爲一種解決方法,我創建了一個「監視」表中,包含一個標誌,指示各特定的工作是否是「真」運行與否,和到期時間警惕失敗。所以,如果這個標誌表明一個作業沒有運行,那麼它就無法運行,所以啓動它是安全的。如果它指示它正在運行,那麼我使用sp_help_job方法來檢查作業是否正在運行。如果這返回它沒有運行。我碰到一個櫃檯並繼續。 – DarinH 2011-05-27 14:27:26

+0

如果計數器在它們之間連續碰撞x次,那麼我可以合理確定該作業實際上並未運行,清除其狀態並使其可以再次運行。屁股疼痛,但它始終如一地工作。 – DarinH 2011-05-27 14:27:39

+0

儘管 – DarinH 2011-05-27 14:27:59

回答

4

首先,你有機會來看看服務代理?從你的描述來看,這聽起來就是你真正想要的。

不同之處在於您將數據放入SB隊列,SB會調用您的處理過程異步完成與已經運行的作業等相關的步驟問題。它會自動產生/終止附加線程和需求使然,它需要的順序等

護理這裏有一個很好的(和隱約相關)的教程。 http://www.sqlteam.com/article/centralized-asynchronous-auditing-with-service-broker

讓我們假設你不能使用SB無論出於何種原因(但嚴重的是,這樣做!)。

怎麼樣使用作業SPID的CONTEXT_INFO。

  1. 你的工作調用了一個包裝處理程序,它執行每個單獨的步驟。
  2. 包裝proc中的第一個語句是

    DECLARE @context_info VARBINARY(30) 
    SET @context_info = CAST('MyJob1' AS VARBINARY) 
    SET CONTEXT_INFO @context_info 
    
  3. 當你的PROC完成(或你的catch塊)

    SET CONTEXT_INFO 0x0 
    
  4. 當你正在尋找在呼喚你的工作,做到這一點:

    IF NOT EXISTS (SELECT * FROM master..sysprocesses WITH (NOLOCK) WHERE context_info=CAST('MyJob1' AS VARBINARY)) 
        EXEC StartJob 
    

當包裝程序終止或連接關閉時,context_info消失。

你也可以使用全局臨時表(即## JobStatus),他們將消失的時候引用它的所有的spid斷開,或者如果它的顯式刪除。

只是一些想法。

+0

仍然希望少一點迂迴的解決方案我不瞭解Context_info功能。有趣的是,儘管在當天結束時,該方法與使用表格基本相同,其中包含作業的SPID和一些跟蹤信息的行。雖然可能有點簡單(因爲上下文信息在作業完成時會自動消失) – DarinH 2011-08-04 04:11:25

+0

我最初考慮了ServiceBroker,但客戶卻認爲他們沒有人知道關於員工的任何信息。在我的腦海裏爲了類似的將來的項目。謝謝! – DarinH 2011-08-04 04:15:23

+0

我給這個答案點頭,主要是因爲1)它提到了我以前沒有用過的CONTEXT_INFO,2)它基本上是我最終使用工作跟蹤表,儘管全局臨時表可能是一個+ +清理器,因爲它會自動清理自己,而對於普通表,我必須確保事情得到明確清理。 – DarinH 2011-08-15 13:51:05

-3

要與已經運行的工作對策: 1.打開任務管理器 2.檢查是否有ImageName「DTExec.exe」進程正在運行 3.如果正在運行的進程,如果它是有問題的工作,執行「結束進程」。

+0

沒有在尋找手動解決方案。 – DarinH 2013-07-11 11:53:10

2

我有一個查詢,讓我正在運行的作業,或許它可以幫助你。它一直在爲我工作,但如果你發現它有任何問題,讓我知道,我會盡力糾正。乾杯。

-- get the running jobs 
--marcelo miorelli 
-- 10-dec-2013 


SELECT sj.name 
     ,DATEDIFF(SECOND,aj.start_execution_date,GetDate()) AS Seconds 
FROM msdb..sysjobactivity aj 
JOIN msdb..sysjobs sj on sj.job_id = aj.job_id 
WHERE aj.stop_execution_date IS NULL -- job hasn't stopped running 
AND aj.start_execution_date IS NOT NULL -- job is currently running 
--AND sj.name = 'JobName' 
and not exists(-- make sure this is the most recent run 
    select 1 
    from msdb..sysjobactivity new 
    where new.job_id = aj.job_id 
     and new.start_execution_date > aj.start_execution_date) 
相關問題