3. 作业创建与配置实战
SQL Server 代理作业(SQL Server Agent Job)是自动化运维的核心执行单元。一个作业由若干“步骤”组成,步骤之间通过“成功流”和“失败流”决定执行顺序;作业还可以把每个步骤的输出写入操作系统文件,并把执行历史保存在 msdb 系统库中。本节以“每日凌晨 2:00 对业务库执行索引维护并记录结果”为例,分别用 SSMS 图形界面和 T-SQL 脚本完成创建与配置,重点讲清步骤、控制流、输出文件和历史记录四件事。
一、先明确作业的四个组成要素
在动手之前,需要先建立对象模型:作业本身只承载名称、所有者、分类、启用状态和调度;真正干活的是步骤;步骤之间的先后关系由“成功时转到第几步 / 失败时转到第几步”决定;输出文件和历史记录则负责留痕。理解这四层关系,后面的配置就不会乱。
二、用 SSMS 创建作业
在对象资源管理器中展开“SQL Server 代理”,右键“作业”→“新建作业”,打开“新建作业”对话框。该对话框左侧有“常规、步骤、计划、警报、通知、目标”六个页面,本节只涉及前三个。
常规页:填写名称 DBA_IndexMaintenance_Daily,所有者保持 sa 或专用运维账号,分类选择“数据库维护”,勾选“已启用”。
步骤页:点击“新建”,弹出“新建作业步骤”窗口。步骤名填 1_RebuildIndex,类型选“Transact-SQL 脚本(T-SQL)”,数据库选 BizDB,命令框输入:
SET NOCOUNT ON;
ALTER INDEX ALL ON dbo.Orders
REBUILD WITH (ONLINE = ON, MAXDOP = 4);
PRINT 'RebuildIndex finished at ' + CONVERT(varchar(19), GETDATE(), 120);
切到“高级”页,这里就是控制流和输出文件的关键位置:
- “成功时要执行的操作”:选择“转到下一步”,即成功后进入步骤 2。
- “失败时要执行的操作”:选择“转到步骤”,并指定第 3 步,即失败时跳过统计信息更新,直接告警。
- “重试次数”设为 1,“重试间隔(分钟)”设为 2,用于应对偶发的锁等待。
- “输出文件”勾选“将输出追加到现有文件”,路径填
C:\JobLog\IndexMaint.txt。
按同样方式新建步骤 2 2_UpdateStatistics,命令为 UPDATE STATISTICS dbo.Orders WITH FULLSCAN;,成功时“退出报告成功的作业”,失败时“转到步骤 3”。步骤 3 3_SendAlert 类型选“操作系统(CmdExec)”,命令用 sqlcmd 或 powershell 发送邮件,成功时退出。
计划页:点击“新建”,频率选“每天”,执行时间 02:00:00,持续时间“无结束日期”。保存后作业即处于启用状态。
NT SERVICE\SQLSERVERAGENT)对该目录要有写权限,否则步骤会因无法写入而失败。三、用 T-SQL 创建同样的作业
图形界面适合一次性配置,批量部署和版本化则更适合脚本。核心存储过程是 msdb.dbo.sp_add_job、sp_add_jobstep、sp_add_jobschedule 和 sp_add_jobserver。
USE msdb;
GO
EXEC dbo.sp_add_job
@job_name = N'DBA_IndexMaintenance_Daily',
@enabled = 1,
@description = N'每日索引维护与统计信息更新';
EXEC dbo.sp_add_jobstep
@job_name = N'DBA_IndexMaintenance_Daily',
@step_id = 1,
@step_name = N'1_RebuildIndex',
@subsystem = N'TSQL',
@database_name = N'BizDB',
@command = N'ALTER INDEX ALL ON dbo.Orders REBUILD WITH (ONLINE=ON, MAXDOP=4);',
@on_success_action = 3, -- 3 = 转到下一步
@on_fail_action = 4, -- 4 = 转到指定步骤
@on_fail_step_id = 3,
@retry_attempts = 1,
@retry_interval = 2,
@output_file_name = N'C:\JobLog\IndexMaint.txt',
@flags = 2; -- 2 = 追加到现有文件
EXEC dbo.sp_add_jobstep
@job_name = N'DBA_IndexMaintenance_Daily',
@step_id = 2,
@step_name = N'2_UpdateStatistics',
@subsystem = N'TSQL',
@database_name = N'BizDB',
@command = N'UPDATE STATISTICS dbo.Orders WITH FULLSCAN;',
@on_success_action = 1, -- 1 = 退出报告成功
@on_fail_action = 4,
@on_fail_step_id = 3;
EXEC dbo.sp_add_jobstep
@job_name = N'DBA_IndexMaintenance_Daily',
@step_id = 3,
@step_name = N'3_SendAlert',
@subsystem = N'CmdExec',
@command = N'powershell.exe -File C:\Scripts\SendAlert.ps1',
@on_success_action = 1,
@on_fail_action = 2; -- 2 = 退出报告失败
EXEC dbo.sp_add_schedule
@schedule_name = N'Daily_0200',
@freq_type = 4, -- 4 = 每天
@freq_interval = 1,
@active_start_time = 20000;
EXEC dbo.sp_attach_schedule
@job_name = N'DBA_IndexMaintenance_Daily',
@schedule_name = N'Daily_0200';
EXEC dbo.sp_add_jobserver
@job_name = N'DBA_IndexMaintenance_Daily';
其中 @on_success_action 与 @on_fail_action 的取值需要记牢:1 退出报告成功,2 退出报告失败,3 转到下一步,4 转到指定步骤。这正是图形界面“成功流/失败流”背后的参数。
四、输出文件与历史记录
输出文件保存的是步骤运行时控制台产生的文本,包括 PRINT 输出、错误信息和影响行数,适合排查细节。历史记录则保存在 msdb.dbo.sysjobhistory,记录每次运行的步骤、状态、开始时间、耗时和消息。查询最近一次执行结果:
SELECT TOP 10
j.name AS job_name,
h.step_id,
h.step_name,
h.run_status, -- 0失败 1成功 2重试 3取消 4进行中
h.run_date,
h.run_time,
h.run_duration,
h.message
FROM msdb.dbo.sysjobhistory h
JOIN msdb.dbo.sysjobs j ON j.job_id = h.job_id
WHERE j.name = N'DBA_IndexMaintenance_Daily'
ORDER BY h.run_date DESC, h.run_time DESC;
历史记录默认只保留一定条数,可在“SQL Server 代理属性”→“历史记录”页设置“每个作业的最大历史记录行数”和“最大历史记录行数”,也可用 sp_purge_jobhistory 手动清理。输出文件不会自动清理,需要配合维护计划或脚本定期归档,避免磁盘被日志撑满。
sysjobhistory.run_status,再核对每个步骤的 on_fail_action,不要只看作业整体状态。五、验证与常见判断依据
配置完成后,右键作业选择“作业开始步骤”,手动执行一次。判断是否达成目标的依据有三条:一是作业历史中三个步骤的 run_status 是否按预期流转;二是输出文件是否按追加方式写入并包含时间戳;三是失败场景下是否真的跳到了步骤 3。可以故意把步骤 1 的表名改成不存在的对象,观察失败流是否生效,验证后再改回。这样一套“创建—配置—触发—看历史—看文件”的闭环,才是作业治理真正可复用的基础。