2012年4月8日 星期日

SQL Server Express 自動化管理 (三) 異常警示


資料庫運行過程中,有時會發生不可預期的狀況,需要 DBA 作即時的處理;此時便可利用 SQL Server 所提供的 Database Mail Server 來傳送 Email 訊息給相關維修人員。不幸的,SQL Server 2008 R2 Express 的 Mangement Studio 並不提供此種設定的介面。因此,本人在此將介紹一解決方案,以自行開發的程式來達到相同的效果。共可分為 4 部分 --

  • Check_DB_Size.bat :DOS Batch 檔案,透過 sqlmd 呼叫 Stored Procedure –> usp_DB_Size_Checker 以進行資料庫實體檔案大小檢查作業。
  • usp_DB_Size_Checker: SQL Server Stored Procedure,存在於欲監視的資料庫中,負責檢查該資料庫實體檔案大小;當超過警示值時,便呼叫另一 Stored Procedure --> usp_Alert_Sender 進行警示 Email 傳送作業。
  • usp_Alert_Sender:負責傳送 Email (此處呼叫 gmail 進行訊息的傳送)。
  • 工作排程器:Windows 所內附功能,負責定時呼叫 Check_DB_Size.bat (以 Windows 7 進行說明)。 

建置步驟

1) 在安裝 SQL Server 2008 R2 Express 的電腦上,確定目錄 C:\Home\Expense 已經存在。


2) 用文章 (SQL Server 2008 R2 Express 自動化管理 (一) 定期備份) 建立的 Expense 資料庫、DETAIL_RECORD Table。      


3) 建立一個供排程作業使用的 Check_DB_Size.bat DOS Batch 檔案,並將其存放到 C:\Home\Expense 目錄。內容如下:
@echo off

sqlcmd -S localhost\SQLEXPRESS -E -d Expense -Q "exec usp_DB_Size_Checker"


4) 撰寫 usp_Alert_Sender Stored Procedure,並於 SQL Server 的 Expense 資料庫中編譯 (Compile);此處假設由 Gmail 的 xxx@gmail.com 帳號送出警示 Email 給 Hotmail 的 yyy@hotmail.com 帳號。
use Expense;

if object_id ('usp_Alert_Sender') is not null
   drop proc usp_Alert_Sender
go

Create Proc usp_Alert_Sender @prm_database_name varchar(200)
as
   declare @acnt_id                 int,
           @msg_1                   varchar(50),
           @msg_2                   varchar(50),
           @prof_id                 int

   declare @db_mail_server_status   varchar(20),
           @sql                     nvarchar(2000),
           @prof_name               sysname,
           @acnt_name               sysname

   declare @tbl_db_mail_server table (d_status varchar(20))

   set nocount on

   -- 初始化 ---------------------------------------------
   select @prof_name = 'DB Administrator Profile'
   select @acnt_name = 'DBA_1'
   ------------------------------------------------------ 
 
   -- 啟動 DB Mail Server --------------------------------
   exec sp_configure 'show advanced options', 1
   reconfigure

   exec sp_configure 'Database Mail XPs', 1
   reconfigure   
 
   exec msdb.dbo.sysmail_start_sp; 
   ------------------------------------------------------ 
 
   -- 檢查 Account 是否已存在 -----------------------------
   -- 若不存在, 則建立新的 Account 。
   if not exists(select * from msdb.dbo.sysmail_account where name = @acnt_name)
      exec msdb.dbo.sysmail_add_account_sp
                   @account_name        = @acnt_name,
                   @description         = 'Alert Message Account',
                   @email_address       = 'xxx@gmail.com',
                   @replyto_address     = 'xxx@gmail.com',
                   @display_name        = 'DB Alert',
                   @mailserver_name     = 'smtp.gmail.com',
                   @port                = 587,
                   @username            = 'xxx@gmail.com',
                   @password            = 'Your Gmail Password',
                   @enable_ssl          = 1
 
   -- 取得 Profile 的 ID 值
   select @prof_id = profile_id from msdb.dbo.sysmail_profile
   ------------------------------------------------------

   -- 檢查 Profile 是否已存在 -----------------------------
   -- 若不存在, 則建立新的 Profile 。
   if not exists(select * from msdb.dbo.sysmail_profile where name = @prof_name)
      exec msdb.dbo.sysmail_add_profile_sp @profile_name = @prof_name
 
   -- 取得 Account 的 ID 值
   select @acnt_id = account_id from msdb.dbo.sysmail_account 
   ------------------------------------------------------

   -- 檢查該 Account 是否已被加入此 Profile ----------------
   -- 若尚未加入, 則將其加入 。
   if not exists(select pa.*
                   from msdb.dbo.sysmail_profileaccount pa,
                        msdb.dbo.sysmail_profile p,
                        msdb.dbo.sysmail_account a
                  where pa.profile_id = p.profile_id
                    and pa.account_id = a.account_id)
    begin
       exec msdb.dbo.sysmail_add_profileaccount_sp
          @profile_id      = @prof_id,
          @account_id      = @acnt_id,
          @sequence_number = 1

       -- 授權 DBMailUsers 可使用此 Profile
       exec msdb.dbo.sysmail_add_principalprofile_sp
          @profile_id      = @prof_id,
          @principal_name  = 'public',
          @is_default      = 1   
    end
   ------------------------------------------------------

   -- 傳送 Alert Email -----------------------------------
   select @msg_1 = @prm_database_name + ' Database is about to exceed 10 GB !'
   select @msg_2 = 'SQL Server: ' + @prm_database_name + ' DB Warning'
 
   exec msdb.dbo.sp_send_dbmail
      @recipients   = 'yyy@hotmail.com',
      @body         = @msg_1,
      @subject      = @msg_2,
      @profile_name = @prof_name
   ------------------------------------------------------

   set nocount off

   return

5) 撰寫 usp_DB_Size_Checker Stored Procedure,並於 SQL Server 的 Expense 資料庫中編譯 (Compile),內容如下:
use Expense;

if object_id ('usp_DB_Size_Checker') is not null
   drop proc usp_DB_Size_Checker
go

Create Proc usp_DB_Size_Checker
as
   declare @alert_boundary   int,
           @size             int,
           @size_string      varchar(30)
     
   declare @tbl_db_info table (
              t_name         varchar(200),  
              t_size         varchar(20),  
              t_owner        varchar(50),  
              t_dbid         int,  
              t_created      datetime,  
              t_status       varchar(4000),  
              t_compat       int)  

   set nocount on

   -- 設定資料庫檔案大小警戒值為 10 GB * 90% 
   select @alert_boundary = 10 * 1000000 * 0.9  -- 單位:MB
 
   -- 找出 Expense 目前的檔案大小 ------------------------
   insert into @tbl_db_info exec sp_helpdb

   select @size_string = t_size 
     from @tbl_db_info
    where t_name = 'Expense'
  
   select @size_string = t_size
     from @tbl_db_info
    where t_name = 'Expense'

   select @size = cast(replace(@size_string, ' MB', '') as real)
   ----------------------------------------------------

   -- 當資料庫檔案大小 >= 10 GB * 90% 時, 呼叫 usp_Alert_Sender 發出通知。
   if @size >= @alert_boundary
      exec usp_Alert_Sender 'Expense'

   set nocount off

   return


6) 作排程器設定為每天下午 06:00:00 進行資料庫大小檢查作業:(螢幕左下方) 開始 --> 所有程式 --> 附屬應用程式 --> 系統工具 --> 工作排程器

(1). 於 "工作排程器" 視窗中,highlight 畫面左方的 "工作排程器程式庫"後,按一下滑鼠右鍵,選取 "建立工作"。
(2). 此時將出現 "建立工作" 視窗 (目前位於 "一般" 頁籤)。
(3). 在 "名稱" 欄位輸入 DB Size Check,勾選 "只有使用者登入時才執行"、"以最高權限執行" 欄位後,點選上方 "觸發程序" 頁籤繼續設定。
(4). 於 "觸發程序" 頁籤點選 "新增",出現 "新增觸發程序" 視窗 --
  • 選擇 "每天"。
  • "開始" 欄位,選取 2012/4/1 下午 06:00:00 。
  • "每隔" 欄位,選取 "1" 天。
  • 按下 "確定" 功能鍵後,點選上方 "動作" 頁籤繼續設定。
(5). 於 "動作" 頁籤點選 "新增",此時出現 "新的執行動作" 視窗 --
  • "執行" 欄位,選取 "啟動程式"。
  • 按下 "瀏覽",於出現的視窗中,選擇 C:\Home\Expense\Check_DB_Size.bat,按 "開啟舊檔"。
  • 按下 "確定" 功能鍵後,再按一次 "確定"。
自 2012/4/1 起,每天下午 06:00:00 便會自動檢查 Expense 資料庫大小,並適時發出警示 Email。