作業介紹
SQL SERVER的作業是一系列由SQL SERVER代理按順序執行的指定操作。作業可以執行一系列活動,包括運行Transact-SQL腳本、命令行應用程序、Microsoft ActiveX腳本、Integration Services 包、Analysis Services 命令和查詢或復制任務。作業可以運行重復任務或那些可計划的任務,它們可以通過生成警報來自動通知用戶作業狀態,從而極大地簡化了 SQL Server 管理[參見MSDN]。
創建作業、刪除作業、查看作業歷史記錄....等所有操作都可以通過SSMS管理工具GUI界面操作,有時候也確實挺方便的。但是當一個實例有多個作業或多個數據庫實例時,通過圖形化的界面去管理、維護作業也是個頭痛的問題,對於SQL腳本與GUI界面管理維護作業熟優熟劣這個問題,只能說要看場合。下面主要介紹通過SQL腳本來管理、維護作業。
作業分類
創建作業時,往往需要指定作業類別,如果不指定新建作業類別,就會默認為“[未分類(本地)]”,如下截圖所示:
當然,你可以查看、添加、刪除、修改作業分類。請看下面操作。
1:查看作業分類
- --method 1:
- EXEC msdb.dbo.sp_help_category;
- GO
- --method 2:
- SELECT category_id ,--作業類別ID
- category_class ,--類別中項目類型:1=作業2=警報 3=操作員
- category_type ,--類別中類型:=本地、=多服務器、=無
- name --分類名稱
- FROMmsdb.dbo.syscategories
有興趣的可以研究一下存儲過程msdb.dbo.sp_help_category

SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON GO CREATE PROCEDURE sp_help_category @class VARCHAR(8) = 'JOB', @type VARCHAR(12) = NULL, @name sysname = NULL, @suffix BIT = 0 AS BEGIN DECLARE @retval INT DECLARE @type_in VARCHAR(12) DECLARE @category_type INT DECLARE @category_class INT DECLARE @where_clause NVARCHAR(255) DECLARE @cmd NVARCHAR(255) SET NOCOUNT ON SELECT @class = LTRIM(RTRIM(@class)) SELECT @type = LTRIM(RTRIM(@type)) SELECT @name = LTRIM(RTRIM(@name)) IF (@type = '') SELECT @type = NULL IF (@name = N'') SELECT @name = NULL IF (@class = 'JOB') AND (@type IS NULL) SELECT @type_in = 'LOCAL' ELSE IF (@class <> 'JOB') AND (@type IS NULL) SELECT @type_in = 'NONE' ELSE SELECT @type_in = @type EXECUTE @retval = sp_verify_category @class, @type_in, NULL, @category_class OUTPUT, @category_type OUTPUT IF (@retval <> 0) RETURN(1) IF (@suffix <> 0) SELECT @suffix = 1 IF @name IS NOT NULL AND NOT EXISTS(SELECT * FROM msdb.dbo.syscategories WHERE name = @name AND category_class = @category_class) BEGIN DECLARE @category_class_string NVARCHAR(25) SET @category_class_string = CAST(@category_class AS nvarchar(25)) RAISERROR(14526, -1, -1, @name, @category_class_string) RETURN(1) END SELECT @where_clause = N'WHERE (category_class = ' + CONVERT(NVARCHAR, @category_class) + N') ' IF (@name IS NOT NULL) SELECT @where_clause = @where_clause + N'AND (name = N' + QUOTENAME(@name, '''') + N') ' IF (@type IS NOT NULL) SELECT @where_clause = @where_clause + N'AND (category_type = ' + CONVERT(NVARCHAR, @category_type) + N') ' SELECT @cmd = N'SELECT category_id, ' IF (@suffix = 1) BEGIN SELECT @cmd = @cmd + N'''category_type'' = ' SELECT @cmd = @cmd + N'CASE category_type ' SELECT @cmd = @cmd + N'WHEN 0 THEN ''NONE'' ' SELECT @cmd = @cmd + N'WHEN 1 THEN ''LOCAL'' ' SELECT @cmd = @cmd + N'WHEN 2 THEN ''MULTI-SERVER'' ' SELECT @cmd = @cmd + N'WHEN 3 THEN ''NONE'' ' SELECT @cmd = @cmd + N'ELSE FORMATMESSAGE(14205) ' SELECT @cmd = @cmd + N'END, ' END ELSE BEGIN SELECT @cmd = @cmd + N'category_type, ' END SELECT @cmd = @cmd + N'name ' SELECT @cmd = @cmd + N'FROM msdb.dbo.syscategories ' EXECUTE (@cmd + @where_clause + N'ORDER BY category_type, name') RETURN(@@error) END GO
2:添加作業分類
如下所示,添加一個叫"DBA_MONITORING"的作業分類
- EXEC msdb.dbo.sp_add_category
- @class=N'JOB',
- @type=N'LOCAL',
- @name=N'DBA_MONITORING' ;
- GO
- SELECT * FROM msdb.dbo.syscategories WHERE NAME='DBA_MONITORING'
- category_id category_class category_type name
- ----------- -------------- ------------- -------------
- 102 1 1 DBA_MONITORING
有興趣的可以研究一下存儲過程msdb.dbo.sp_add_category

SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON GO CREATE PROCEDURE sp_add_category @class VARCHAR(8) = 'JOB', @type VARCHAR(12) = 'LOCAL', @name sysname AS BEGIN DECLARE @retval INT DECLARE @category_type INT DECLARE @category_class INT SET NOCOUNT ON SELECT @class = LTRIM(RTRIM(@class)) SELECT @type = LTRIM(RTRIM(@type)) SELECT @name = LTRIM(RTRIM(@name)) EXECUTE @retval = sp_verify_category @class, @type, @name, @category_class OUTPUT, @category_type OUTPUT IF (@retval <> 0) RETURN(1) IF (EXISTS (SELECT * FROM msdb.dbo.syscategories WHERE (category_class = @category_class) AND (name = @name))) BEGIN RAISERROR(14261, -1, -1, '@name', @name) RETURN(1) END INSERT INTO msdb.dbo.syscategories (category_class, category_type, name) VALUES (@category_class, @category_type, @name) RETURN(@@error) END GO
3:刪除作業分類
如下所示,刪除一個叫"DBA_MONITORING" 的作業分類
- EXEC msdb.dbo.sp_delete_category
- @name = N'DBA_MONITORING',
- @class = N'JOB' ;
- GO
有興趣的可以研究一下存儲過程msdb.dbo.sp_delete_category

SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON GO CREATE PROCEDURE sp_delete_category @class VARCHAR(8), @name sysname AS BEGIN DECLARE @retval INT DECLARE @category_id INT DECLARE @category_class INT DECLARE @category_type INT SET NOCOUNT ON SELECT @class = LTRIM(RTRIM(@class)) SELECT @name = LTRIM(RTRIM(@name)) EXECUTE @retval = sp_verify_category @class, NULL, NULL, @category_class OUTPUT, NULL IF (@retval <> 0) RETURN(1) SELECT @category_id = category_id, @category_type = category_type FROM msdb.dbo.syscategories WHERE (category_class = @category_class) AND (name = @name) IF (@category_id IS NULL) BEGIN RAISERROR(14262, -1, -1, '@name', @name) RETURN(1) END IF (@category_id < 100) BEGIN RAISERROR(14276, -1, -1, @name, @class) RETURN(1) END BEGIN TRANSACTION UPDATE msdb.dbo.sysjobs SET category_id = CASE @category_type WHEN 1 THEN 0 WHEN 2 THEN 2 END WHERE (category_id = @category_id) UPDATE msdb.dbo.sysalerts SET category_id = 98 WHERE (category_id = @category_id) UPDATE msdb.dbo.sysoperators SET category_id = 99 WHERE (category_id = @category_id) DELETE FROM msdb.dbo.syscategories WHERE (category_id = @category_id) COMMIT TRANSACTION RETURN(0) END GO
4:修改作業類別
msdb.dbo.sp_update_category
[@class =] 'class' ,
[@name =] 'old_name' ,
[@new_name =] 'new_name' |
有興趣的可以研究一下存儲過程msdb.dbo.sp_update_category

SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON GO CREATE PROCEDURE sp_update_category @class VARCHAR(8), @name sysname, @new_name sysname AS BEGIN DECLARE @retval INT DECLARE @category_id INT DECLARE @category_class INT SET NOCOUNT ON SELECT @class = LTRIM(RTRIM(@class)) SELECT @name = LTRIM(RTRIM(@name)) SELECT @new_name = LTRIM(RTRIM(@new_name)) IF @name = '' SELECT @name = NULL EXECUTE @retval = sp_verify_category @class, NULL, @new_name, @category_class OUTPUT, NULL IF (@retval <> 0) RETURN(1) IF @name IS NOT NULL AND NOT EXISTS(SELECT * FROM msdb.dbo.syscategories WHERE name = @name AND category_class = @category_class) BEGIN RAISERROR(14526, -1, -1, @name, @category_class) RETURN(1) END SELECT @category_id = category_id FROM msdb.dbo.syscategories WHERE (category_class = @category_class) AND (name = @new_name) IF (@category_id IS NOT NULL) BEGIN RAISERROR(14261, -1, -1, '@new_name', @new_name) RETURN(1) END IF (@category_id < 100) BEGIN RAISERROR(14276, -1, -1, @name, @class) RETURN(1) END UPDATE msdb.dbo.syscategories SET name = @new_name WHERE (category_class = @category_class) AND (name = @name) RETURN(@@error) END GO
分析上面四個存儲過程可以看出,實質上新增、修改、刪除、查看作業類別無非就是對表 msdb.dbo.syscategories進行操作,只是通過存儲過程封裝了而已,增加了驗證等操作,確保數據完整性。
新建作業
創建作業的步驟一般如下所示:
- 執行 sp_add_job 來創建作業。
-
執行 sp_add_jobstep 來創建一個或多個作業步驟。
-
執行 sp_add_schedule 來創建計划。
-
執行 sp_attach_schedule 將計划附加到作業。
-
執行 sp_add_jobserver 來設置作業的服務器。
本地作業是由本地 SQL Server 代理進行緩存的。因此,任何修改都會隱式強制 SQL Server 代理重新緩存該作業。由於直到調用 sp_add_jobserver 時,SQL Server 代理才緩存作業,因此最后調用 sp_add_jobserver 將更為有效。
下面看用腳本新建一個作業用來每天執行exec sp_cycle_errorlog ,實現錯誤日志循環, 從下面的腳本量來看,用腳本新建一個作業確實工作量很大,而且容易出錯,GUI圖形界面創建作業要方便得多,但是如果遷移數據庫時,用腳本來新建作業是相當方便的。比GUI圖形界面新建一個作業快捷方便多了。
- USE [msdb]
- GO
- /****** Object: Job [JOB_CYCLE_ERRORLOG] Script Date: 08/23/2013 15:25:09 ******/
- IFEXISTS(SELECT job_id FROM msdb.dbo.sysjobs_view WHERE name = N'JOB_CYCLE_ERRORLOG')
- EXEC msdb.dbo.sp_delete_job@job_id=N'a5dff08b-95f8-498e-a6c9-59241fe197b4', @delete_unused_schedule=1
- GO
- USE [msdb]
- GO
- /****** Object: Job [JOB_CYCLE_ERRORLOG] Script Date: 08/23/2013 15:25:09 ******/
- BEGIN TRANSACTION
- DECLARE @ReturnCode INT
- SELECT @ReturnCode = 0
- /****** Object: JobCategory [DBA_MATIANCE] Script Date: 08/23/2013 15:25:09 ******/
- IF NOT EXISTS(SELECT name FROM msdb.dbo.syscategories WHERE name=N'DBA_MATIANCE' AND category_class=1)
- BEGIN
- EXEC @ReturnCode = msdb.dbo.sp_add_category@class=N'JOB', @type=N'LOCAL', @name=N'DBA_MATIANCE'
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- END
- DECLARE @jobId BINARY(16)
- EXEC @ReturnCode =msdb.dbo.sp_add_job@job_name=N'JOB_CYCLE_ERRORLOG',
- @enabled=1,
- @notify_level_eventlog=0,
- @notify_level_email=0,
- @notify_level_netsend=0,
- @notify_level_page=0,
- @delete_level=0,
- @description=N'每天執行exec sp_cycle_errorlog 實現錯誤日志循環。',
- @category_name=N'DBA_MATIANCE',
- @owner_login_name=N'sa', @job_id = @jobId OUTPUT
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- /****** Object: Step [Step 1: recycle the errorlog] Script Date: 08/23/2013 15:25:09 ******/
- EXEC @ReturnCode = msdb.dbo.sp_add_jobstep@job_id=@jobId, @step_name=N'Step 1: recycle the errorlog',
- @step_id=1,
- @cmdexec_success_code=0,
- @on_success_action=1,
- @on_success_step_id=0,
- @on_fail_action=2,
- @on_fail_step_id=0,
- @retry_attempts=0,
- @retry_interval=0,
- @os_run_priority=0, @subsystem=N'TSQL',
- @command=N'exec msdb.dbo.sp_cycle_errorlog',
- @database_name=N'msdb',
- @flags=0
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'Job Schedule',
- @enabled=1,
- @freq_type=4,
- @freq_interval=1,
- @freq_subday_type=1,
- @freq_subday_interval=0,
- @freq_relative_interval=0,
- @freq_recurrence_factor=0,
- @active_start_date=20130823,
- @active_end_date=99991231,
- @active_start_time=0,
- @active_end_time=235959,
- @schedule_uid=N'2099c694-cd26-4edf-8803-179227bf8770'
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
- IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
- COMMIT TRANSACTION
- GOTO EndSave
- QuitWithRollback:
- IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
- EndSave:
- GO
作業系統表
與作業有關的系統表、視圖大致有下面9個,下面就不費口舌詳細解說每一個系統表的作用了,MSDN文檔上有詳細的解說,有興趣的翻看一下即可。
SELECT * FROM msdb.dbo.sysjobs --存儲將由 SQL Server 代理執行的各個預定作業的信息
SELECT * FROM msdb.dbo.sysjobschedules --包含將由 SQL Server 代理執行的作業的計划信息
SELECT * FROM msdb.dbo.sysjobactivity; --記錄當前 SQL Server 代理作業活動和狀態
SELECT * FROM msdb.dbo.sysjobservers --存儲特定作業與一個或多個目標服務器的關聯或關系
SELECT * FROM msdb.dbo.sysjobsteps; --包含 SQL Server 代理要執行的作業中的各個步驟的信息
SELECT * FROM msdb.dbo.sysjobstepslogs; --包含所有 SQL Server 代理作業步驟的作業步驟日志
SELECT * FROM msdb.dbo.sysjobs_view; --
SELECT * FROM msdb.dbo.sysjobhistory --包含有關 SQL Server 代理執行預定作業的信息
SELECT * FROM msdb.dbo.syscategories --包含由 SQL Server Management Studio 用來組織作業、警報和操作員的類別
運行作業
啟動作業
1:通過SSMS工具啟動作業[參見MSDN]
2:通過SQL命令啟動作業
啟動作業一般通過sp_start_job來實現,具體語法與操作見下面。
語法: sp_start_job { [@job_name =] 'job_name' | [@job_id =] job_id } [ , [@error_flag =] error_flag] [ , [@server_name =] 'server_name'] [ , [@step_name =] 'step_name'] [ , [@output_flag =] output_flag] 例子: exec msdb.dbo.sp_start_job @job_name='JOB_CYCLE_ERRORLOG'
停止作業
1:通過SSMS工具停作業[參見MSDN]
2:通過SQL命令停止作業
語法: sp_stop_job [@job_name =] 'job_name' | [@job_id =] job_id | [@originating_server =] 'master_server' | [@server_name =] 'target_server' 例子: exec msdb.dbo.sp_stop_job @job_name='JOB_CYCLE_ERRORLOG'
啟用或禁用作業
1:通過SSMS工具啟用作業[參見MSDN]
2:通過SQL命令禁用作業
語法:
sp_update_job [ @job_id =] job_id | [@job_name =] 'job_name' [, [@new_name =] 'new_name' ] [, [@enabled =] enabled ] [, [@description =] 'description' ] [, [@start_step_id =] step_id ] [, [@category_name =] 'category' ] [, [@owner_login_name =] 'login' ] [, [@notify_level_eventlog =] eventlog_level ] [, [@notify_level_email =] email_level ] [, [@notify_level_netsend =] netsend_level ] [, [@notify_level_page =] page_level ] [, [@notify_email_operator_name =] 'email_name' ] [, [@notify_netsend_operator_name =] 'netsend_operator' ] [, [@notify_page_operator_name =] 'page_operator' ] [, [@delete_level =] delete_level ] [, [@automatic_post =] automatic_post ]
列子:
EXEC msdb.dbo.sp_update_job @job_name = N'JOB_CYCLE_ERRORLOG', @enabled = 0 ; --0 禁用作業、 1啟用作業 GO
刪除作業
1:通過SSMS工具刪除作業[參見MSDN]
2:通過SQL命令刪除作業
語法: sp_delete_job { [ @job_id = ] job_id | [ @job_name = ] 'job_name' } , [ , [ @originating_server = ] 'server' ] [ , [ @delete_history = ] delete_history ] [ , [ @delete_unused_schedule = ] delete_unused_schedule ] 例子: EXEC msdb.dbo.sp_delete_job @job_name = 'JOB_CYCLE_ERRORLOG';
遷移作業
使用 Transact-SQL 編寫作業腳本
-
在對象資源管理器中,連接到 Microsoft SQL Server 數據庫引擎實例,再展開該實例。
-
展開“SQL Server 代理”,再展開“作業”,然后右鍵單擊要編寫腳本的作業。
-
從快捷菜單中,選擇“編寫作業腳本為”,再選擇“CREATE 到”或“DROP 到”,並單擊下列內容之一:
新查詢編輯器窗口,將打開一個新的查詢編輯器窗口,並為其編寫 Transact-SQL 腳本。
文件,將 Transact-SQL 腳本保存到文件。
剪貼板,將 Transact-SQL 腳本保存到剪貼板
常用管理作業SQL
1:查看屬於某個數據庫的所有作業。
- SELECT j.job_id AS JOB_ID ,
- name AS JOB_NAME ,
- enabled AS JOB_ENABLED ,
- description AS JOB_DESCRIPTION ,
- date_created AS DATE_CREATED ,
- date_modified AS DATE_MODIFIED
- FROM msdb.dbo.sysjobs j
- WHERE job_id IN( SELECTjob_id
- FROM msdb.dbo.sysjobsteps
- WHERE database_name = 'DataBaseName' )
2:查看某個作業類別的所有作業
- SELECT j.name AS Job_Name ,
- j.description AS Job_Description ,
- j.date_created AS Date_Created ,
- j.date_modified AS Date_Modified ,
- c.name AS Job_Class
- FROM msdb.dbo.sysjobs j
- LEFT JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
- WHEREc.name = '[Uncategorized (Local)]'
3:查看禁用/啟用的作業
SELECT * FROM msdb.dbo.sysjobs WHERE enabled=0 --0:禁用 1:為啟用
4:查看出錯的作業記錄
4.1:查詢那些作業在今天出錯(如果要查詢歷史出錯作業,去掉查詢時間條件即可)
- SELECT name AS JOB_NAME ,
- description AS JOB_Description ,
- date_created AS Date_Created ,
- date_modified AS Date_Modified
- FROM msdb.dbo.sysjobs
- WHERE enabled = 1
- AND job_id IN(
- SELECT job_id
- FROM Msdb.dbo.sysjobhistory
- WHERE run_status = 0
- AND run_date = CAST(CONVERT(VARCHAR(8), GETDATE(), 112) AS INT) )
4.2:查看出錯詳細信息
- SELECT j.name AS JOB_NAME ,
- h.step_id AS STEP_ID ,
- h.step_name AS STEP_NAME,
- h.message AS ERR_MSG ,
- h.run_date AS RUN_DATE ,
- h.run_time AS RUN_TIME ,
- msdb.dbo.agent_datetime(h.run_date, h.run_time) AS 'RunDateTime' ,
- CAST(run_duration / 10000 AS VARCHAR(2)) + N'小時'
- + CAST(( run_duration - run_duration / 10000 * 10000 ) / 100 AS VARCHAR(2))
- + N'分鍾' + SUBSTRING(CAST(run_duration AS VARCHAR(10)),
- LEN(CAST(run_duration AS VARCHAR(10))) - 1, 2)
- + N'秒' AS run_duration
- FROM msdb.dbo.sysjobhistory h
- LEFT JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id
- WHERE run_status = 0
- AND run_date = CAST(CONVERT(VARCHAR(8), GETDATE(), 112) AS INT)
5:查看作業的執行時間:
5.1:查看當天成功執行的作業的時間(查看的是作業Step信息)
- SELECT j.name AS job_name ,
- h.step_id AS step_id ,
- h.step_name AS step_name,
- h.message AS Message ,
- h.run_date AS Run_date ,
- h.run_time AS run_time ,
- msdb.dbo.agent_datetime(h.run_date, h.run_time) AS 'RunDateTime' ,
- CAST(run_duration / 10000 AS VARCHAR(2)) + N'小時'
- + CAST(( run_duration - run_duration / 10000 * 10000 ) / 100 AS VARCHAR(2))
- + N'分鍾' + SUBSTRING(CAST(run_duration AS VARCHAR(10)),
- LEN(CAST(run_duration AS VARCHAR(10))) - 1, 2)
- + N'秒' AS run_duration
- FROM msdb.dbo.sysjobhistory h
- LEFT JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id
- WHERE run_status = 1
- AND run_date = CAST(CONVERT(VARCHAR(8), GETDATE(), 112) AS INT)
- ORDER BY run_duration DESC
5.2:查詢每個作業的執行時間、按執行時間降序
- SELECT j.name AS JOB_NAME ,
- h.run_date AS RUN_DATE ,
- SUM(run_duration) AS SUM_DURATION
- FROM msdb.dbo.sysjobhistory h
- LEFT JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id
- WHERE run_status = 1
- AND run_date = CAST(CONVERT(VARCHAR(8), GETDATE(), 112) AS INT)
- GROUP BY name ,
- run_date
- ORDER BY Sum_Duration DESC
參考資料: