先把两个问题分开

检查自动备份时,常见的困惑是:备份似乎仍在运行,SQL Server Agent 的作业历史里却没有本次结果。这两个现象可以同时存在。

正在运行的请求,适合从 sys.dm_exec_requests 观察;已经完成的作业和步骤,则要查 Agent 作业历史。把它们混在一起看,很容易把“还没写历史”误判成“任务没有运行”。

第一步:看当前有没有备份请求

下面的查询只读取运行状态,不启动、取消或修改备份任务。

SELECT
    GETDATE() AS observed_at,
    r.session_id,
    r.command,
    r.start_time,
    r.status,
    r.percent_complete,
    CASE WHEN r.estimated_completion_time > 0
         THEN CAST(r.estimated_completion_time / 60000.0
                   AS decimal(18, 2))
    END AS estimated_minutes_remaining,
    r.wait_type,
    r.wait_time,
    r.blocking_session_id
FROM sys.dm_exec_requests AS r
WHERE r.command LIKE N'BACKUP%';

这里值得关注的是连续变化:间隔一段时间再查,完成百分比是否增长,等待是否变化,请求是否最终结束。单次截图只能说明观察时刻的状态。

剩余时间是动态估算,可能波动,也可能暂时没有有用的数值。不要把它当成完成承诺。若查询权限不足,应由有相应监控权限的管理员核对;不同 SQL Server 版本的 DMV 权限要求可能不同。

第二步:正确理解 suspended 和等待类型

suspended 表示请求正在等待某种资源或事件。看到这个状态,需要继续看等待类型、阻塞会话以及进度变化。

原始排查记录里出现过 ASYNC_IO_COMPLETION,同时没有普通会话阻塞。这个组合提示应进一步关注异步 I/O,而不是只凭状态名认定死锁,或立即终止备份。若进度长期不动、磁盘异常或出现错误日志,仍需要继续排查。

第三步:在合适的时间查作业历史

Microsoft 文档说明,sysjobhistory 的数据在多数情况下于作业步骤完成后更新;通常没有正在执行步骤的历史记录,也存在部分进程会写入运行中信息的例外。

DECLARE @JobName sysname = N'替换为备份作业名称';
DECLARE @Today int = CONVERT(int, CONVERT(char(8), GETDATE(), 112));

SELECT TOP (30)
    h.step_id,
    h.step_name,
    h.run_status,
    h.run_date,
    h.run_time,
    h.run_duration,
    h.message
FROM msdb.dbo.sysjobhistory AS h
JOIN msdb.dbo.sysjobs AS j ON j.job_id = h.job_id
WHERE j.name = @JobName
  AND h.run_date >= @Today
ORDER BY h.instance_id DESC;

step_id = 0 对应作业整体结果,其他编号对应具体步骤。应同时看作业整体和实际执行备份的步骤,避免把中间步骤成功当成整个作业成功。

怎样才算核对完整

  • 运行中:能找到目标备份请求,持续观察进度与等待。
  • 结束后:核对作业整体、备份步骤和相关错误信息。
  • 可恢复性:成功历史只证明相应任务报告成功;恢复演练需要另行安排和验证。

这套方法的重点,是让每一种证据回答它擅长回答的问题。历史记录为空,本身不足以证明失败;请求从 DMV 消失,本身也不能证明备份成功。