Joh*_*ers 5 sql-server sql-server-agent log
我想将一些日志提取到报告中,以便获取夜间运行的 SQL_Agent_Jobs 状态。如果作业失败,那么我想在表中接收错误日志。我试图通过以下查询获取该信息:
DECLARE @job_id UNIQUEIDENTIFIER
SELECT
@job_id = job_id FROM msdb.dbo.sysjobs
WHERE
[name] like '%JOB_1%'
OR [name] like '%JOB_2%'
OR [name] like '%JOB_3%'
OR [name] like '%JOB_4%'
OR [name] like '%JOB_5%'
;WITH Error_Output (job_id, error_log) AS
(
SELECT
JS.job_id,
CASE
WHEN JSL.[log] IS NULL THEN JH.[Message]
ELSE JSL.[log]
END AS LogOutput
FROM
msdb.dbo.sysjobsteps JS
INNER JOIN msdb.dbo.sysjobhistory JH
ON JS.job_id = JH.job_id AND JS.step_id = JH.step_id
LEFT OUTER JOIN msdb.dbo.sysjobstepslogs JSL
ON JS.step_uid = JSL.step_uid
WHERE
INSTANCE_ID >
(SELECT
MIN(INSTANCE_ID)
FROM
(SELECT top (2)
INSTANCE_ID, job_id
FROM
msdb.dbo.sysjobhistory
WHERE
job_id = @job_id
AND STEP_ID = 0
ORDER BY
INSTANCE_ID desc
) A
)
AND JS.step_id <> 0
AND JH.job_id = @job_id
AND JH.run_status = 0
)
SELECT
sj.name AS [Job Name]
,MAX(sja.run_requested_date) AS [Start Date]
,MAX(sja.start_execution_date) AS [Effective Start Date]
,MAX(sja.stop_execution_date) AS [Effective End Date]
,DATEDIFF(MINUTE, MAX(sja.start_execution_date), MAX(sja.stop_execution_date)) as [Job Execution Time - M]
,CASE WHEN error_log IS NULL THEN 'Job runs successfully' else error_log end as [Job Log]
FROM
msdb.dbo.sysjobactivity AS sja
INNER JOIN msdb.dbo.sysjobs AS sj ON sja.job_id = sj.job_id
LEFT OUTER JOIN Error_Output AS error ON error.job_id = sja.job_id AND error.job_id = sj.job_id
WHERE
[name] like '%JOB_1%'
OR [name] like '%JOB_2%'
OR [name] like '%JOB_3%'
OR [name] like '%JOB_4%'
OR [name] like '%JOB_5%'
GROUP BY
sj.name, error_log
Run Code Online (Sandbox Code Playgroud)
但是,我总是得到作业运行“作业运行成功”,并且我已经测试并发现作业执行失败。我什至将 SQL_Agent_Job 配置为在作业失败时接收电子邮件,并且我已收到电子邮件,并且查询中的状态不会更改为错误日志(失败)。
我做错了什么?
我写了一篇关于从 msdb 检索作业状态的文章,您可以在此处查看。该帖子中的代码不会从 中提取数据,但如果您要登录到该表,dbo.sysjobstepslogs
则可以非常简单地扩展该代码以从中提取最后一条错误消息。dbo.sysjobstepslogs
默认情况下,作业步骤不会记录到 msdb。要将作业步骤配置为记录到dbo.sysjobstepslogs
,您必须进入作业中每个步骤的作业步骤属性,访问“高级”选项卡,然后选择“记录到表”选项:
然后,您可以创建此表值函数来获取最新的作业状态。我已经修改了上面帖子中的代码,以便还从作业中提取最新的错误(如果可用):
CREATE FUNCTION dbo.SqlAgentJob_GetStatus (@JobName sysname)
RETURNS TABLE
AS
RETURN
SELECT TOP 1
JobName = j.name,
IsRunning = CASE
WHEN ja.job_id IS NOT NULL
AND ja.stop_execution_date IS NULL
THEN 1 ELSE 0
END,
RequestSource = ja.run_requested_source,
LastRunTime = ja.start_execution_date,
NextRunTime = ja.next_scheduled_run_date,
LastJobStep = js.step_name,
RetryAttempt = jh.retries_attempted,
JobLastOutcome = CASE
WHEN ja.job_id IS NOT NULL
AND ja.stop_execution_date IS NULL THEN 'Running'
WHEN jh.run_status = 0 THEN 'Failed'
WHEN jh.run_status = 1 THEN 'Succeeded'
WHEN jh.run_status = 2 THEN 'Retry'
WHEN jh.run_status = 3 THEN 'Cancelled'
END,
LastError = (SELECT TOP 1 jsl.log
FROM msdb.dbo.sysjobstepslogs jsl
WHERE jsl.step_uid = js.step_uid
AND jsl.date_modified >= ja.start_execution_date)
FROM msdb.dbo.sysjobs j
LEFT JOIN msdb.dbo.sysjobactivity ja
ON ja.job_id = j.job_id
AND ja.run_requested_date IS NOT NULL
AND ja.start_execution_date IS NOT NULL
LEFT JOIN msdb.dbo.sysjobsteps js
ON js.job_id = ja.job_id
AND js.step_id = ja.last_executed_step_id
LEFT JOIN msdb.dbo.sysjobhistory jh
ON jh.job_id = j.job_id
AND jh.instance_id = ja.job_history_id
WHERE j.name = @JobName
ORDER BY ja.start_execution_date DESC;
GO
Run Code Online (Sandbox Code Playgroud)
最后,您可以利用 TVF 查询作业状态、最后运行的步骤、最后记录的错误等:
--Specific jobs
SELECT sts.*
FROM msdb.dbo.sysjobs j
CROSS APPLY dbo.SqlAgentJob_GetStatus (j.name) sts
WHERE
j.[name] like '%JOB_1%'
OR j.[name] like '%JOB_2%'
OR j.[name] like '%JOB_3%'
OR j.[name] like '%JOB_4%'
OR j.[name] like '%JOB_5%';
--Failed Jobs
SELECT sts.*
FROM msdb.dbo.sysjobs j
CROSS APPLY dbo.SqlAgentJob_GetStatus (j.name) sts
WHERE sts.JobLastOutcome <> 'Succeeded';
Run Code Online (Sandbox Code Playgroud)