5

sp_start_jobは仕事を始めるために使用します。

ジョブ(test2)には1つのステップしかありません。

select getdate()
waitfor delay '00:00:10'

TRY/CATCHコード:

begin try
    EXEC msdb.dbo.sp_start_job @job_name = 'test2'
end try
begin catch
    print 'error'
end catch

コードの最初の実行:

ジョブ「test2」が正常に開始されました。

コードの2回目の実行(10秒以内):

メッセージ22022、レベル16、状態1、行0
SQLServerAgentエラー:ユーザーsaによる要求からジョブが既に実行されているため、(ユーザーsaからの)ジョブtest2の実行要求が拒否されました。

TRY/CATCHこのシナリオで機能しないのはなぜですか?

更新:最初に、サーバーがリンクされているSQL Server 2005(SQL Server 2000)で作業していることを追加する必要があります。リンクされたすべてのサーバーでジョブを確認するために、SQLServer2005サーバーでプロシージャを作成しようとしました。ジョブが実行されていない場合は、実行します。最初は、try --catchを使用し、すでに実行中のジョブを実行したときにエラーをキャッチしたいと思っていましたが、失敗しました(このスレッド)。

私はついに次のコードを使用しました:(コンパイルされません、いくつかの変数を置き換える必要があります、ただアイデアを与えるだけです)

    CREATE TABLE [dbo].[#jobInfo](
        [job_id] [uniqueidentifier] NULL,
        [originating_server] [nvarchar](30) ,
        [name] [nvarchar](128) ,
        [enabled] [tinyint] NULL,
        [description] [nvarchar](512) ,
        [start_step_id] [int] NULL,
        [category] [nvarchar](128) ,
        [owner] [nvarchar](128) ,
        [notify_level_eventlog] [int] NULL,
        [notify_level_email] [int] NULL,
        [notify_level_netsend] [int] NULL,
        [notify_level_page] [int] NULL,
        [notify_email_operator] [nvarchar](128) ,
        [notify_netsend_operator] [nvarchar](128) ,
        [notify_page_operator] [nvarchar](128) ,
        [delete_level] [int] NULL,
        [date_created] [datetime] NULL,
        [date_modified] [datetime] NULL,
        [version_number] [int] NULL,
        [last_run_date] [int] NOT NULL,
        [last_run_time] [int] NOT NULL,
        [last_run_outcome] [int] NOT NULL,
        [next_run_date] [int] NOT NULL,
        [next_run_time] [int] NOT NULL,
        [next_run_schedule_id] [int] NOT NULL,
        [current_execution_status] [int] NOT NULL,
        [current_execution_step] [nvarchar](128) ,
        [current_retry_attempt] [int] NOT NULL,
        [has_step] [int] NULL,
        [has_schedule] [int] NULL,
        [has_target] [int] NULL,
        [type] [int] NOT NULL
    )


    SET @sql = 
    'INSERT INTO #jobInfo
    SELECT * FROM OPENQUERY( [' + @srvName + '],''set fmtonly off exec msdb.dbo.sp_help_job'')'

    EXEC(@sql)

    IF EXISTS (select * from #jobInfo WHERE [name] = @jobName AND current_execution_status IN (4,5)) -- 4: idle, 5: suspended 
    BEGIN
        SET @sql = 'EXEC [' + @srvName + '].msdb.dbo.sp_start_job @job_name = ''' + @jobName + ''''
        --print @sql    
        EXEC (@sql) 
        INSERT INTO #result (srvName ,status ) VALUES (@srvName, 'Job started.')
    END ELSE BEGIN
        INSERT INTO #result (srvName ,status ) VALUES (@srvName, 'Job is running already. No action taken.')
    END
4

4 に答える 4

8

すべてのエラーをでキャッチできるわけではありませんTRY/CATCH。この場合、sp_start_job実際には外部プロシージャを呼び出しますが、これらはSQLServerのエラー処理の範囲外です。または、少なくともそれは彼らが固執している話です:

http://connect.microsoft.com/SQLServer/feedback/details/362112/sp-start-job-error-handling

また、これはSQL Server 2012SP1CU3でも問題であることに注意してください。このバグを修正したい場合は、投票してコメントしてください。

面倒ですが実行可能な回避策。特定の権限が必要であり、この場合、ジョブの所有者は次のsaとおりです。

DECLARE @x TABLE
(
  a VARBINARY(32),b INT,c INT,d INT,e INT,f INT,g INT,h INT,i NVARCHAR(64),
  Running BIT, -- the only important column
  k INT,l INT,m INT
);

DECLARE @job_id UNIQUEIDENTIFIER;

SELECT @job_id = job_id FROM msdb.dbo.sysjobs WHERE name = N'test2';

INSERT @x EXEC master.dbo.xp_sqlagent_enum_jobs 1, N'sa', @job_id;

IF EXISTS (SELECT 1 FROM @x WHERE Running = 0)
BEGIN
     EXEC msdb.dbo.sp_start_job @job_name = N'test2';
END
ELSE
BEGIN
     PRINT 'error';
END

さらに良いかもしれません:

DECLARE @job_id UNIQUEIDENTIFIER, @d DATETIME;

SELECT @job_id = job_id FROM msdb.dbo.sysjobs WHERE name = N'test2';

SELECT @d = stop_execution_date 
  FROM msdb.dbo.sysjobactivity WHERE job_id = @job_id;

IF @d IS NOT NULL
BEGIN
     EXEC msdb.dbo.sp_start_job @job_name = N'test2';
END
ELSE
BEGIN
     PRINT 'error';
END

いずれの場合も、ステータスの確認から開始の呼び出しまでの間にジョブが開始された可能性があるため、エラーをsp_start_job完全に排除することはできませんが、エラーが発生する可能性ははるかに低くなります。

于 2013-03-27T12:48:02.013 に答える
1

アラートを使用してSQLエージェントジョブを実行できます。また、アラートのオプションを使用して、必要な応答を構成できます。(これは、エラー22022を完全に回避するのに役立ちますが、エラーログに追加のレコードがあります)

于 2018-08-08T10:56:40.977 に答える
0

ジョブトリガーの失敗をキャプチャする方法は次のとおりです。

@returnstatusintを宣言します

Exec @returnstatusmsdb.dbo.sp_start_job'ジョブ名'

if(@returnstaus = 1)Print'Success' else Print'Failure'

于 2020-11-04T08:33:26.523 に答える
0

常緑のソリューションを作成するには、これまで実行されたことのないジョブも検討する必要があります。これは、SQLサーバーが再構築されてジョブが再作成されるシナリオで役立ちます。そのシナリオをキャプチャするには、最後の実行要求日を確認します。

DECLARE @jobEnd DATETIME, @jobRun DATETIME
SELECT @jobEnd = sja.stop_execution_date , @jobRun = sja.run_requested_date
FROM msdb.dbo.sysjobactivity AS sja
INNER JOIN msdb.dbo.sysjobs AS sj
ON sja.job_id = sj.job_id
WHERE sj.name = 'PhoneListSyncMember'

IF (@jobEnd IS NOT NULL AND @jobRun IS NOT NULL)
  OR (@jobEnd IS NULL AND @jobRun IS NULL)  -- job is New and never run before
    EXEC @iRet =msdb.dbo.sp_start_job @job_name='PhoneListSyncMember'
于 2021-05-20T00:14:20.857 に答える