как узнать статус текущих работ

Мне нужно знать, выполняется ли данное задание в настоящее время на сервере Ms SQL 2008. Чтобы не вызывать снова одно и то же задание, которое может привести к проблемам с параллелизмом.


person TonyP    schedule 26.08.2013    source источник
comment
Монитор активности заданий в разделе агента SQL Server SSMS.   -  person Khan    schedule 26.08.2013


Ответы (8)


Похоже, вы можете использовать msdb.dbo.sysjobactivity, проверяя запись с ненулевым start_execution_date и нулевым значением stop_execution_date, что означает, что задание было запущено, но еще не завершено.

Это даст вам текущие рабочие места:

SELECT sj.name
   , sja.*
FROM msdb.dbo.sysjobactivity AS sja
INNER JOIN msdb.dbo.sysjobs AS sj ON sja.job_id = sj.job_id
WHERE sja.start_execution_date IS NOT NULL
   AND sja.stop_execution_date IS NULL
person Adam Wenger    schedule 26.08.2013
comment
Это сообщает о некоторых невыполненных заданиях на моих серверах. - person Paul; 20.03.2014
comment
Я недостаточно знаю о системной активности. Я просто знаю, что у меня есть работа, которая соответствует вашим критериям для моей деятельности в прошлом. то есть не текущее или не последнее. Работа в настоящее время неактивна. Я не знаю, означает ли это отмену или незапланированную перезагрузку и т. Д. (SQL2008R2) - person Paul; 20.03.2014
comment
@Paul. Если вы задали свой вопрос по этому поводу, возможно, мы сможем получить больше информации о вашей проблеме и, возможно, придумать решения - разобраться в этом в комментариях не всегда легко. - person Adam Wenger; 20.03.2014
comment
Я просто почувствовал, что, когда я увидел что-то не так с этим ответом, я должен что-то сказать, чтобы будущие люди не приняли это абсолютно в лицо. Мне уже пришлось пока отойти от этой темы. - person Paul; 21.03.2014
comment
Сюда входят задания, которые были начаты, но не завершены из-за ошибок. EXEC msdb.dbo.sp_help_job работает лучше - person alastairtree; 28.04.2014
comment
@Paul использует session_ID для преодоления старых значений сеанса ... с помощью sysjobhistory вы можете проверить, не удалось ли выполнить задание, тогда мы также можем избежать этих результатов. - person MarmiK; 02.07.2014
comment
@Paul: Я считаю, что следующий ответ StackOverflow может помочь вам: stackoverflow.com/a/18062236/216440 Это включает только действия из текущего сеанса агента SQL. См. Также stackoverflow.com/a/13038752/216440 для объяснения того, как могут застревать записи активности из предыдущих сеансов. - person Simon Tewsi; 25.08.2014
comment
Неправильный ответ, потому что здесь также перечислены запущенные задания. - person user1328350; 16.01.2015
comment
У меня есть лучший ответ здесь dba.stackexchange.com/questions/58859/, см. ответ Кеннета Фишера, который возвращает только выполняемые в данный момент задания - person Niraj; 09.02.2016
comment
@AdamWenger Моя виртуальная машина с SQL Server потеряла питание во время выполнения задания. В результате JobActivity имеет значение NULL для stop_execution_date, несмотря на то, что многие другие экземпляры задания успешно завершились после этого сбоя. - person colbybhearn; 08.06.2016

Я нашел лучший ответ Кеннета Фишера. Следующий запрос возвращает только запущенные в данный момент задания:

SELECT
    ja.job_id,
    j.name AS job_name,
    ja.start_execution_date,      
    ISNULL(last_executed_step_id,0)+1 AS current_executed_step_id,
    Js.step_name
FROM msdb.dbo.sysjobactivity ja 
LEFT JOIN msdb.dbo.sysjobhistory jh ON ja.job_history_id = jh.instance_id
JOIN msdb.dbo.sysjobs j ON ja.job_id = j.job_id
JOIN msdb.dbo.sysjobsteps js
    ON ja.job_id = js.job_id
    AND ISNULL(ja.last_executed_step_id,0)+1 = js.step_id
WHERE
  ja.session_id = (
    SELECT TOP 1 session_id FROM msdb.dbo.syssessions ORDER BY agent_start_date DESC
  )
AND start_execution_date is not null
AND stop_execution_date is null;

Вы можете получить больше информации о вакансии, добавив дополнительные столбцы из msdb.dbo.sysjobactivity таблицы в предложение select.

person Niraj    schedule 09.02.2016
comment
Одной из важных особенностей этого сценария является то, что он выбирает только задания, выполняемые в текущем сеансе SQL-агента. Задания, которые выполнялись на момент завершения предыдущего сеанса агента SQL, также будут иметь значение NULL stop_execution_date. Мы хотим их исключить, поэтому ja.session_id = (SELECT TOP 1 session_id FROM msdb.dbo.syssessions ORDER BY agent_start_date DESC) - person Simon Tewsi; 26.02.2016
comment
Вероятно, следует оставить этот ответ как ссылку на исходный ответ, а не копировать код, потому что есть полезный комментарий, выделяющий ограничение: «К сожалению, этот сценарий предполагает, что текущий выполняемый шаг - это шаг после последнего завершенного шага. Это не всегда так » - person JonoB; 02.10.2020
comment
как найти ошибки, которые могли возникнуть во время выполнения задания? - person Golden Lion; 30.04.2021

EXEC msdb.dbo.sp_help_job @Job_name = 'Your Job Name'

проверьте поле Execution_status

0 - возвращает только те задания, которые не простаивают и не приостановлены.
1 - Выполняется.
2 - Ожидание потока.
3 - Между повторными попытками.
4 - Ожидание.
5 - Приостановлено. .
7 - Выполнение действий завершения.

Если вам нужен результат выполнения, проверьте поле last_run_outcome

0 = Не удалось
1 = Успешно
3 = Отменено
5 = Неизвестно

https://msdn.microsoft.com/en-us/library/ms186722.aspx

person Nicholas Giudice    schedule 26.05.2015

Учитывая вакансию (я полагаю, вы знаете ее название), вы можете использовать:

EXEC msdb.dbo.sp_help_job @Job_name = 'Your Job Name'

как предложено в Процедуре справки по вакансиям MSDN. Он возвращает много информации о задании (владелец, сервер, статус и т. Д.).

person Francesco De Lisi    schedule 26.08.2013

EXECUTE master.dbo.xp_sqlagent_enum_jobs 1,''

Обратите внимание на столбец Выполняется, очевидно, 1 означает, что он в настоящее время выполняется, и [Текущий шаг]. Это вернет вам job_id, поэтому вам нужно будет найти их, например:

SELECT top 100 *
 FROM   msdb..sysjobs
 WHERE  job_id IN (0x9DAD1B38EB345D449EAFA5C5BFDC0E45, 0xC00A0A67D109B14897DD3DFD25A50B80, 0xC92C66C66E391345AE7E731BFA68C668)
person David Rodecker    schedule 14.07.2014

Мы нашли и используем этот код в качестве хорошего решения. Этот код запускает задание и отслеживает его, автоматически завершая задание, если оно превышает установленный временной лимит.

/****************************************************************
--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.'
person Community    schedule 23.02.2017
comment
Спасибо! Это отлично сработало для нас с некоторыми незначительными изменениями. - person ; 07.06.2017

Этот запрос даст вам точный результат для текущих запущенных заданий. Это также покажет продолжительность выполняемого задания в минутах.

   WITH
    CTE_Sysession (AgentStartDate)
    AS 
    (
        SELECT MAX(AGENT_START_DATE) AS AgentStartDate FROM MSDB.DBO.SYSSESSIONS
    )   
SELECT sjob.name AS JobName
        ,CASE 
            WHEN SJOB.enabled = 1 THEN 'Enabled'
            WHEN sjob.enabled = 0 THEN 'Disabled'
            END AS JobEnabled
        ,sjob.description AS JobDescription
        ,CASE 
            WHEN ACT.start_execution_date IS NOT NULL AND ACT.stop_execution_date IS NULL  THEN 'Running'
            WHEN ACT.start_execution_date IS NOT NULL AND ACT.stop_execution_date IS NOT NULL AND HIST.run_status = 1 THEN 'Stopped'
            WHEN HIST.run_status = 0 THEN 'Failed'
            WHEN HIST.run_status = 3 THEN 'Canceled'
        END AS JobActivity
        ,DATEDIFF(MINUTE,act.start_execution_date, GETDATE()) DurationMin
        ,hist.run_date AS JobRunDate
        ,run_DURATION/10000 AS Hours
        ,(run_DURATION%10000)/100 AS Minutes 
        ,(run_DURATION%10000)%100 AS Seconds
        ,hist.run_time AS JobRunTime 
        ,hist.run_duration AS JobRunDuration
        ,'tulsql11\dba' AS JobServer
        ,act.start_execution_date AS JobStartDate
        ,act.last_executed_step_id AS JobLastExecutedStep
        ,act.last_executed_step_date AS JobExecutedStepDate
        ,act.stop_execution_date AS JobStopDate
        ,act.next_scheduled_run_date AS JobNextRunDate
        ,sjob.date_created AS JobCreated
        ,sjob.date_modified AS JobModified      
            FROM MSDB.DBO.syssessions AS SYS1
        INNER JOIN CTE_Sysession AS SYS2 ON SYS2.AgentStartDate = SYS1.agent_start_date
        JOIN  msdb.dbo.sysjobactivity act ON act.session_id = SYS1.session_id
        JOIN msdb.dbo.sysjobs sjob ON sjob.job_id = act.job_id
        LEFT JOIN  msdb.dbo.sysjobhistory hist ON hist.job_id = act.job_id AND hist.instance_id = act.job_history_id
        WHERE ACT.start_execution_date IS NOT NULL AND ACT.stop_execution_date IS NULL
        ORDER BY ACT.start_execution_date DESC
person Basant Mishra    schedule 14.02.2019

Вы можете запросить таблицу msdb.dbo.sysjobactivity, чтобы определить, выполняется ли задание в данный момент.

person Sonam    schedule 26.08.2013