MS SQL 教學
MIS 或 DBA 經常會設計定時抓取資料的 Schedule SQL Job,但因為上游資料來源(或程式)延遲或失敗,過了 Job 執行時間也許才差幾秒幾分鐘或可容許的延遲時間內來源資料變已產生完畢了,可是定時抓取的 SQL Job 早已停工,此時 User 來上工了發現系統有問題通知 MIS 處理,這時也只能癡癡地等上游資料跑完後,MIS 再手動執行 SQL JOB... 或者更慘的是,假日被急摳來處理...!!
MIS 轄下受連累的系統因為資料不夠新鮮以致使用單位無法作業,只好吃下問題單 ="=... 接著安排人跟催上遊甚麼時候補好資料庫。
為了能安心休假只好下海找解套......
咱們工程師只會寫程式解決問題所以 SQL 很弱,常常去碰資料庫只為了重新啟動 JOB 當然覺得痛苦。
人在屋簷下不得不低頭,到了 user site 古人 MIS 已經搞了一堆 SQL 跑來跑去,只好配合在這個模式下找出不讓系統開發人員痛苦的解決方案!
其實用個簡單的 MS SQL 涵式,就可以解決這個惱人的問題了!
(轉貼時請加註來源)
引用自:藍色小惡魔《自動重新啟動資料庫工作排程》
http://www.imp.idv.tw/play/forum/viewthread?thread=2191
SQL 2000 : sp_update_jobschedule
SQL 2005, 2008 : sp_update_schedule (建議) or sp_update_jobschedule (為相容 2000 而殘留的)
只要兩個簡單的要素即可高枕無憂
1. 要能判斷是否需重新執行的方法。
2. 要建立一個執行一次的 job schedule。
你的 JOB 應該有兩個 Schedule 如下,第一個是你正常應該要啟動的、一個是當有問題的時候需要被啟動的(disable),這個 shcedule 在以下範例我命名為 reschedule。
接著你要依資料庫版本查出重新啟動 schedule 的 key,use msdb 後參考以下方法找出 schedule_id 或 job_id。
SQL 2005, 2008 使用 scuedule_id 即可,可透過管理工具的作業屬性中的排程清單找到 schedule_id,或使用和 SQL 2000 相同指令也可,以上圖為例,ID 506 就是 @schedule_id。
SQL 2000 只能用 job_id,則需呼叫 exec sp_help_job @job_name = '[JOB NAME]',以上圖為例 @job_name = 'ADM_LETTERS_COUNT (2009-11-20)'。取得 @job_id = '499235D9-4EB1-45C5-A66D-1D4D53BA1C98'
然後我以如果資料更新失敗,則一個小時後重新執行一次為例,如下:
-- 主要資料處理 SQL (建議規劃防重複執行判斷)
INSERT ADM_LETTERS_COUNT SELECT ...
-- 第一要素:設計判斷資料更新失敗的邏輯
declare @adm_data_date_diff int
set @adm_data_date_diff = (select datediff(day, max(ADMLC_DATADATE), getdate()) from ADM_LETTERS_COUNT)
-- 第二要素:判斷需要重新啟動則安排一小時候執行 (以下範例會跑到當天凌晨才停止,建議可再設計停跑時間。)
if(@adm_data_date_diff > 1) begin
declare @today int, @new_datetime datetime, @new_time int
set @today = convert(int, convert(char(8), getdate(), 112))
set @new_datetime = dateadd(hour, 1, getdate())
set @new_time = datepart(hour, @new_datetime)*10000+datepart(minute, @new_datetime)*100
use msdb
/* for SQL 2005 new function
exec sp_update_schedule @schedule_id = 506, @enabled = 1, @active_start_date = @today, @active_start_time = @new_time
--*/
exec sp_update_jobschedule
@job_id = '499235D9-4EB1-45C5-A66D-1D4D53BA1C98',
@name = 'reschedule', @enabled = 1,
@active_start_date = @today,
@active_start_time = @new_time
end
為了易懂以上簡化程式碼,其他加強的機制可以再繼續自行應用。
以下簡單舉例防重複執行判斷並不難,只要把第一要素套上來即可,如下...
declare @adm_data_date_diff int
set @adm_data_date_diff = (select datediff(day, max(ADMLC_DATADATE), getdate()) from ADM_LETTERS_COUNT)
if(@adm_data_date_diff > 1) begin
INSERT ADM_LETTERS_COUNT SELECT ...
end
set @adm_data_date_diff = (select datediff(day, max(ADMLC_DATADATE), getdate()) from ADM_LETTERS_COUNT)
if(@adm_data_date_diff > 1) begin
declare @today int, @new_datetime datetime, @new_time int
...(略)...
exec sp_update_jobschedule @job_id ...
end
留言列表