2012-05-23 12 views
8

चल रहा है परिदृश्यएसक्यूएल एजेंट नौकरी: निर्धारित करें कि कितना समय

कुछ एसक्यूएल एजेंट नौकरियां दिन भर में हर कुछ मिनट चलाने के लिए निर्धारित कर रहे हैं कि कर रहे हैं।

वैध समय हैं जब यह अपने अगले शेड्यूल को याद करेगा क्योंकि यह अभी भी पिछले शेड्यूल से चल रहा है।

प्रत्येक बार और थोड़ी देर में, एक नौकरी 'लटका' सकती है। यह विफलता उत्पन्न नहीं करता है (क्योंकि नौकरी अभी तक बंद नहीं हुई है)। जब ऐसा होता है, तो नौकरी मैन्युअल रूप से रुक सकती है और अगली बार चलने पर ठीक काम करती है। यह बैक अप लेने के लिए डिज़ाइन किया गया है जहां यह छोड़ा गया था।

सबसे कुशल तरीका क्या है ...?

मुझे यह निर्धारित करने का एक तरीका चाहिए कि एसक्यूएल एजेंट जॉब नामक एक एसक्यूएल एजेंट जॉब वर्तमान में चल रहा है। यदि यह वर्तमान में चल रहा नहीं है, तो हम शून्य वापस कर सकते हैं।

इस तरह, अगर मैं एक निश्चित दहलीज से अधिक समय तक चल रहा हूं तो मैं नौकरी रोक सकता हूं।

मुझे लगता है कि xp_sqlagent_enum_jobs और sysjobhistory का संयोजन उपयोग किया जा सकता है, लेकिन अगर वहां बेहतर समाधान हैं तो मैं उत्सुक हूं ... और उम्मीद है कि आप में से बाकी बाधाओं से लाभ हो सकता है और बाकी के आसपास काम किया है ।

+1

चेक। हमारे पास एक समान समस्या थी, और इस समाधान को लागू किया: [एसक्यूएल "वॉचडॉग" लूप एसक्यूएल एजेंट जॉब्स शुरू करने और निगरानी करने के लिए] (http://cc.davelozinski.com/code/sql-watchdog-loop-start-monitor-sql- एजेंट-नौकरियां) –

उत्तर

17

यह समाधान काम करेगा:

SELECT 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 = 'JobX' 
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 
) 

यह एक अधिक सामान्य जांच प्रणाली टेबल पर निर्भर है। यदि आप एक कस्टम मार्ग पसंद करेंगे, तो आप जॉब लॉग टेबल में जॉब डालने के बजाय आपके द्वारा बनाई गई हो सकती है।

+0

क्या आप इसे इस तरह से कुछ नहीं चाहते हैं, इसे हाल ही की गतिविधि तक सीमित करने के लिए? "आंतरिक मिलान (चयन करें MAX (start_execution_date) एएस स्टार्टडेट, जॉब_आईडी msdb..sysjobactivity समूह से job_id) sj.job_id = MostRecentActivity.job_id और aj.start_execution_date = MostRecentActivity.StartDate" –

+0

आवश्यक नहीं है। यदि आप केवल उस नौकरी की तलाश में हैं जो वर्तमान में चल रहा है और आपके अपेक्षा से अधिक समय तक चल रहा है, तो यह क्वेरी केवल आपके पास वापस आनी चाहिए जो वर्तमान में चल रही है। यदि यह नहीं चल रहा है, तो यह कुछ भी नहीं देता है। – Zhenny

+0

प्रैक्टिस में, वर्तमान में चल रहे नौकरी पर दिए गए परिणाम वास्तव में रिकॉर्ड का एक गुच्छा देता है। उस जॉइन के साथ सीमित करना सही मूल्य देना प्रतीत होता है। मैंने आपका जवाब संशोधित किया और स्वीकार कर लिया। –

1
/**** FOR CURRENTLY RUNNING JOBS ****/ 
SELECT j.name AS Job_Name,DATEDIFF(ss,a.start_execution_date ,GETDATE()) 
FROM msdb.dbo.sysjobactivity a INNER JOIN msdb.dbo.sysjobs j 
ON a.job_id =j.job_id 
WHERE CONVERT(DATE,a.start_execution_date)=CONVERT(DATE,GETDATE()) 
AND a.stop_execution_date IS NULL 


/*This code will give u the Name of currently running jobs and for how much time it is running & after that u can add filters to it as u wish*/ 
/*Thanks in advance*/ 
0

क्या आप मैन्युअल रूप से कर रहे हैं क्या एक "घड़ी कुत्ता पाश" के रूप में जाना जाता है की तरह लगता है। असल में, एक एसक्यूएल नौकरी जो एजेंट नौकरियों को शुरू करती है और/या मॉनीटर करती है, यदि आवश्यकता हो तो उन्हें मारना।

The code below was taken from here, और मदद करनी चाहिए की आवश्यकता नहीं पड़ती आप मैन्युअल रूप से नजर रखने के लिए करने के लिए और नौकरियों को मारने अगर वे समय की एक लंबी अवधि के लिए चल रही है: निम्न आलेख बाहर

/**************************************************************** 
--This SQL will take a list of SQL Agent jobs (names must match), 
--start them so they're all running together, and then 
--monitor them, not quitting until all jobs have completed. 
-- 
--In essence, it's an SQL "watchdog" loop to start and monitor SQL Agent Jobs 
-- 
--Code from http://cc.davelozinski.com/code/sql-watchdog-loop-start-monitor-sql-agent-jobs 
-- 
****************************************************************/ 
SET NOCOUNT ON 

-------- BEGIN ITEMS THAT NEED TO BE CONFIGURED -------- 

--The amount of time to wait before checking again 
--to see if the jobs are still running. 
--Should be in hh:mm:ss format. 
DECLARE @WaitDelay VARCHAR(8) = '00:00:20' 

--Job timeout. Eg, if the jobs are running longer than this, kill them. 
DECLARE @TimeoutMinutes INT = 240 

DECLARE @JobsToRunTable TABLE 
(
    JobName NVARCHAR(128) NOT NULL, 
    JobID UNIQUEIDENTIFIER NULL, 
    Running INT NULL 
) 

--Insert the names of the SQL jobs here. Last two values should always be NULL at this point. 
--Names need to match exactly, so best to copy/paste from the SQL Server Agent job name. 
INSERT INTO @JobsToRunTable (JobName, JobID, Running) VALUES ('NameOfFirstSQLAgentJobToRun',NULL,NULL) 
INSERT INTO @JobsToRunTable (JobName, JobID, Running) VALUES ('NameOfSecondSQLAgentJobToRun',NULL,NULL) 
INSERT INTO @JobsToRunTable (JobName, JobID, Running) VALUES ('NameOfXSQLAgentJobToRun',NULL,NULL) 

-------- NOTHING FROM HERE DOWN SHOULD NEED TO BE CONFIGURED -------- 

DECLARE @ExecutionStatusTable TABLE 
(
    JobID UNIQUEIDENTIFIER PRIMARY KEY, -- Job ID which will be a guid 
    LastRunDate INT, LastRunTime INT, -- Last run date and time 
    NextRunDate INT, NextRunTime INT, -- Next run date and time 
    NextRunScheduleID INT, -- an internal schedule id 
    RequestedToRun INT, RequestSource INT, RequestSourceID VARCHAR(128), 
    Running INT, -- 0 or 1, 1 means the job is executing 
    CurrentStep INT, -- which step is running 
    CurrentRetryAttempt INT, -- retry attempt 
    JobState INT -- 0 = Not idle or suspended, 1 = Executing, 2 = Waiting For Thread, 
        -- 3 = Between Retries, 4 = Idle, 5 = Suspended, 
        -- 6 = WaitingForStepToFinish, 7 = PerformingCompletionActions 
) 

DECLARE @JobNameToRun NVARCHAR(128) = NULL 
DECLARE @IsJobRunning BIT = 1 
DECLARE @AreJobsRunning BIT = 1 
DECLARE @job_owner sysname = SUSER_SNAME() 
DECLARE @JobID UNIQUEIDENTIFIER = null 
DECLARE @StartDateTime DATETIME = GETDATE() 
DECLARE @CurrentDateTime DATETIME = null 
DECLARE @ExecutionStatus INT = 0 
DECLARE @MaxTimeExceeded BIT = 0 

--Loop through and start every job 
DECLARE dbCursor CURSOR FOR SELECT JobName FROM @JobsToRunTable 
OPEN dbCursor FETCH NEXT FROM dbCursor INTO @JobNameToRun 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    EXEC [msdb].[dbo].sp_start_job @JobNameToRun 
    FETCH NEXT FROM dbCursor INTO @JobNameToRun 
END 
CLOSE dbCursor 
DEALLOCATE dbCursor 

print '*****************************************************************' 
print 'Jobs started. ' + CAST(@StartDateTime as varchar) 
print '*****************************************************************' 

--Debug (if needed) 
--SELECT * FROM @JobsToRunTable 

WHILE 1=1 AND @AreJobsRunning = 1 
BEGIN 

    --This has to be first with the delay to make sure the jobs 
    --have time to actually start up and are recognized as 'running' 
    WAITFOR DELAY @WaitDelay 

    --Reset for each loop iteration 
    SET @AreJobsRunning = 0 

    --Get the currently executing jobs by our user name 
    INSERT INTO @ExecutionStatusTable 
    EXECUTE [master].[dbo].xp_sqlagent_enum_jobs 1, @job_owner 

    --Debug (if needed) 
    --SELECT 'ExecutionStatusTable', * FROM @ExecutionStatusTable 

    --select every job to see if it's running 
    DECLARE dbCursor CURSOR FOR 
     SELECT x.[Running], x.[JobID], sj.name 
     FROM @ExecutionStatusTable x 
     INNER JOIN [msdb].[dbo].sysjobs sj ON sj.job_id = x.JobID 
     INNER JOIN @JobsToRunTable jtr on sj.name = jtr.JobName 
    OPEN dbCursor FETCH NEXT FROM dbCursor INTO @IsJobRunning, @JobID, @JobNameToRun 

    --Debug (if needed) 
    --SELECT x.[Running], x.[JobID], sj.name 
    -- FROM @ExecutionStatusTable x 
    -- INNER JOIN msdb.dbo.sysjobs sj ON sj.job_id = x.JobID 
    -- INNER JOIN @JobsToRunTable jtr on sj.name = jtr.JobName 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     --bitwise operation to see if the loop should continue 
     SET @AreJobsRunning = @AreJobsRunning | @IsJobRunning 

     UPDATE @JobsToRunTable 
     SET Running = @IsJobRunning, JobID = @JobID 
     WHERE JobName = @JobNameToRun 

     --Debug (if needed) 
     --SELECT 'JobsToRun', * FROM @JobsToRunTable 

     SET @CurrentDateTime=GETDATE() 

     IF @IsJobRunning = 1 
     BEGIN -- Job is running or finishing (not idle) 

      IF DATEDIFF(mi, @StartDateTime, @CurrentDateTime) > @TimeoutMinutes 
      BEGIN  
       print '*****************************************************************' 
       print @JobNameToRun + ' exceeded timeout limit of ' + @TimeoutMinutes + ' minutes. Stopping.' 
       --Stop the job 
       EXEC [msdb].[dbo].sp_stop_job @job_name = @JobNameToRun 
      END 
      ELSE 
      BEGIN 
       print @JobNameToRun + ' running for ' + CONVERT(VARCHAR(25),DATEDIFF(mi, @StartDateTime, @CurrentDateTime)) + ' minute(s).' 
      END 
     END 

     IF @IsJobRunning = 0 
     BEGIN 
      --Job isn't running 
      print '*****************************************************************' 
      print @JobNameToRun + ' completed or did not run. ' + CAST(@CurrentDateTime as VARCHAR) 
     END 

     FETCH NEXT FROM dbCursor INTO @IsJobRunning, @JobID, @JobNameToRun 

    END -- WHILE @@FETCH_STATUS = 0 
    CLOSE dbCursor 
    DEALLOCATE dbCursor 

    --Clear out the table for the next loop iteration 
    DELETE FROM @ExecutionStatusTable 

    print '*****************************************************************' 

END -- WHILE 1=1 AND @AreJobsRunning = 1 

SET @CurrentDateTime = GETDATE() 
print 'Finished at ' + CAST(@CurrentDateTime as varchar) 
print CONVERT(VARCHAR(25),DATEDIFF(mi, @StartDateTime, @CurrentDateTime)) + ' minutes total run time.' 
संबंधित मुद्दे