資料庫運維中盛傳一個小段子,我誤刪除了資料庫,改怎麼辦?有備份還原備份,沒有備份就準備簡歷!聽起來有趣但發生在誰身上,誰都笑不起來。接觸了很多的客戶發現90%客戶的運維策略都不是很完善。本篇就分享一些常規的運維腳本,本篇沒有涉及到的或不足的也請大家留言無私貢獻深藏多年的腳本,謝謝! 郵件 郵件主要用 ...
資料庫運維中盛傳一個小段子,我誤刪除了資料庫,改怎麼辦?有備份還原備份,沒有備份就準備簡歷!聽起來有趣但發生在誰身上,誰都笑不起來。接觸了很多的客戶發現90%客戶的運維策略都不是很完善。本篇就分享一些常規的運維腳本,本篇沒有涉及到的或不足的也請大家留言無私貢獻深藏多年的腳本,謝謝!
郵件
郵件主要用來監控作業是否運行成功,如果您已經配置了類似zabbix等軟體請忽略。
配置郵件服務
--SQL Server 並沒有內置郵件伺服器(Mail Server),它跟我們發送郵件一樣,需要用戶名和密碼通過 SMTP(Simple Message Transfer Protocol)去連接郵件伺服器。我們想讓 SQL Server 來發送郵件,首先要告訴它用戶名稱,密碼,伺服器地址,網路傳送協議,郵件伺服器的埠。。。等信息。 -- 以下腳本實現了資料庫郵件的配置: ----下麵是具體的配置郵件步驟 ----在 sa 系統帳戶下運行。 -- --1. 啟用 SQL Server 郵件功能。 use master go exec sp_configure 'show advanced options',1 go reconfigure with override go exec sp_configure 'Database Mail XPs',1 go reconfigure with override go --2. 在 SQL Server 中添加郵件帳戶(account) exec msdb..sysmail_add_account_sp @account_name = '163yx' -- 郵件帳戶名稱(SQL Server 使用) ,@email_address = '[email protected]' -- 發件人郵件地址 ,@display_name = null -- 發件人姓名 ,@replyto_address = null ,@description = null ,@mailserver_name = 'smtp.163.com' -- 郵件伺服器地址 ,@mailserver_type = 'SMTP' -- 郵件協議(SQL 2005 只支持 SMTP) ,@port = 25 -- 郵件伺服器埠 ,@username = '[email protected]' -- 用戶名 ,@password = 'XXXXX' -- 密碼 ,@use_default_credentials = 0 ,@enable_ssl = 0 ,@account_id = null --3. 在 SQL Server 中添加 profile exec msdb..sysmail_add_profile_sp @profile_name = 'dba_profile3' -- profile 名稱 ,@description = 'dba mail profile' -- profile 描述 ,@profile_id = null -- 在 SQL Server 中映射 account 和 profile exec msdb..sysmail_add_profileaccount_sp @profile_name = 'dba_profile3' -- profile 名稱 ,@account_name = '163yx' -- account 名稱 ,@sequence_number = 1 -- account 在 profile 中順序 --5. 利用 SQL Server Database Mail 功能發送郵件。 exec msdb..sp_send_dbmail @profile_name = 'dba_profile3' -- profile 名稱 ,@recipients = '[email protected];[email protected]' -- 收件人郵箱 ,@subject = 'SQL Server Mail 測試' -- 郵件標題 ,@body = 'Hello Mail!測試' -- 郵件內容 ,@body_format = 'TEXT' -- 郵件格式 ,@file_attachments = 'c:\a.txt' --郵件附件 --6. 查看郵件發送情況: use msdb go select * from sysmail_allitems select * from sysmail_mailitems select * from sysmail_event_log --如果不是以 sa 帳戶發送郵件,則可能會出現錯誤: -- --Msg 229, Level 14, State 5, Procedure sp_send_dbmail, Line 1 --EXECUTE permission denied on object 'sp_send_dbmail', database 'msdb', schema 'dbo'. -- --這是因為,當前 SQL Server 登陸帳戶(login),在 msdb 資料庫中沒有發送資料庫郵件的許可權,需要加入 msdb 資料庫用戶,並通過加入 sp_addrolemember 角色賦予許可權。假設該SQL Server 登陸帳戶名字為 “dba” -- --use msdb --go -- --create user dba for login dba --go -- --exec dbo.sp_addrolemember @rolename = 'DatabaseMailUserRole', -- @membername = 'dba' --go -- --此時,再次發送資料庫郵件,仍可能有錯誤: -- --Msg 14607, Level 16, State 1, Procedure sp_send_dbmail, Line 119 --profile name is not valid -- --雖然,資料庫用戶 “dba” 已經在 msdb 中擁有發送郵件的許可權了,但這還不夠,他還需要有使用 profile:“dba_profile” 的許可權。 -- --use msdb --go -- --exec sysmail_add_principalprofile_sp @principal_name = 'dba' -- ,@profile_name = 'dba_profile' -- ,@is_default = 1 -- --從上面的參數 @is_default=1 可以看出,一個資料庫用戶可以在多個 mail profile 擁有發送許可權。 --EXEC msdb.dbo.sysmail_configure_sp 'MaxFileSize', 100000000 (位元組)設置郵件.note
配置操作員
操作員主要是用於作業的通知對象:
配置如下:
USE [msdb] GO EXEC msdb.dbo.sp_add_operator @name=N'mail_user2', @enabled=1, @pager_days=0, @email_address=N'KK_XXXX.163.COM' GO
註 :操作員可根據是否在作業成功或失敗時通知,後續腳本均未配置操作員,如需配置可在作業屬性中自行添加
AlwaysOn相關
節點切換監控
declare @role VARCHAR(8000); declare @email_conetent varchar(8000);--存放郵件正文 declare @name varchar(100); declare @lastsend int; declare @subject_str varchar(100); set @name =(select @@servername) set @subject_str = @name + 'always on 預警' set @role=(SELECT role FROM sys.dm_hadr_availability_replica_states WHERE is_local=1) set @lastsend = (select isnull(datediff(MINUTE,max(send_request_date), getdate()),6000) from [msdb].[dbo].[sysmail_mailitems] where subject = @subject_str) if @role >1 and @lastsend > 30 ----30分鐘發送一次 begin set @email_conetent=(@name+'當前節點不是主節點,發生故障轉移') print(@email_conetent) print(@lastsend) --if @lastsend > 1 --發送郵件 --郵件正文內容 EXEC msdb.dbo.sp_send_dbmail @profile_name = 'DB-mail', --配置文件名稱 @recipients = '[email protected]', --收件email地址 @subject = @subject_str, --郵件主題 @body = @email_conetent end
節點切換作業控制
作業可以採用手動控制或如下腳本,也可以修改作業在作業執行前增加節點判斷
--------------------------判斷當前節點是否為主節點 如果不是則禁用作業 ------- ------------節點 切換為主節點則啟用JOB ------------ DECLARE @ROLE tinyint DECLARE @ENABLE tinyint ----判斷是否是主節點 --1 主節點 SELECT @role=role FROM sys.dm_hadr_availability_replica_states WHERE is_local=1 --判斷JOB狀態 --0 禁用 1 啟用 --以syspolicy_purge_history 為 參照 --如果 禁用或刪除syspolicy_purge_history請修改 @ENABLE下段查詢 SELECT @ENABLE = [ENABLED] FROM MSDB.[dbo].[sysjobs] WHERE NAME = 'syspolicy_purge_history' -----第一次切換 輔助節點沒有創建CDC作業 job 則創建作業 [category_id] = 13 CDC LOG SCAN JOB if not exists (select 1 from msdb.dbo.sysjobs where [category_id]= 13 or [category_id]= 16 ) and @ROLE = 1 begin EXEC sys.sp_cdc_add_job @job_type = 'capture'; EXEC sys.sp_cdc_add_job @job_type = 'cleanup'; end ---primary and job disable set job enable IF @ROLE = 1 and @ENABLE = 0 BEGIN ----如果存在原有作業為禁用,無法確定哪些JOB需要開啟....所以此處最好手動維護作業的啟用和禁用 EXEC msdb.dbo.sp_update_job @job_name = N'XXXXX', @enabled = 1 ; -----執行 CDC EXEC msdb.dbo.sp_start_job @job_name = N'cdc.XX_capture' EXEC msdb.dbo.sp_start_job @job_name = N'cdc.XX_cleanup' end ---not primary and job enable set disable IF @ROLE <> 1 and @ENABLE = 1 BEGIN ----如果存在原有作業為禁用,無法確定哪些JOB需要開啟....所以此處最好手動維護作業的啟用和禁用 EXEC msdb.dbo.sp_update_job @job_name = N'XXXXX', @enabled = 0 ; END
數據備份
備份方案:每天全備份、6小時一次差異備份、一小時一次日誌備份。
備份存儲過程
存儲過程創建後會保留在master庫中,存儲過程主要控製備份邏輯,備份路徑等。
存儲過程中只有一個類型參數,用於控制全備/差異/日誌備份,可根據需要修改。
USE [master] GO /****** Object: StoredProcedure [dbo].[sp_BackupDatabase] Script Date: 01/22/2015 13:52:46 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- Author: KK -- Create date: 2016-09-27 -- Description: 備份資料庫,備份路徑F:\KK_BackUp\ 可自行修改 -- http://www.cnblogs.com/double-K/ -- Parameter1: 備份類型 F=全部, D=差異, L=日誌 alter PROCEDURE [dbo].[sp_BackupDatabase] @backupType CHAR(1) AS BEGIN SET NOCOUNT ON; declare @filepath_backup varchar(100) declare @dateTime varchar(30),@del_time_stamp varchar(50) DECLARE @sqlCommand NVARCHAR(1000) ---創建資料庫對應文件夾 EXECUTE master.dbo.xp_create_subdir N'F:\KK_BackUp\Full\' EXECUTE master.dbo.xp_create_subdir N'F:\KK_BackUp\Difference\' EXECUTE master.dbo.xp_create_subdir N'F:\KK_BackUp\Log_Bak\' IF @backupType = 'F' set @filepath_backup='F:\KK_BackUp\Full\' IF @backupType = 'D' set @filepath_backup='F:\KK_BackUp\Difference\' IF @backupType = 'L' set @filepath_backup='F:\KK_BackUp\Log_Bak\' SET ANSI_WARNINGS OFF SET @dateTime = replace(convert(varchar,current_timestamp, 112)+'_'+convert(varchar,current_timestamp, 108),':','') ----刪除超過3天的備份文件 DECLARE @delete_time datetime set @delete_time = getdate() - 3 EXECUTE master.dbo.xp_delete_file 0,N'F:\kk_backup',N'trn',@delete_time,1 EXECUTE master.dbo.xp_delete_file 0,N'F:\kk_backup',N'bak',@delete_time,1 SELECT @dateTime = replace(convert(varchar,current_timestamp, 112)+'_'+convert(varchar,current_timestamp, 108),':','') declare db_info cursor for SELECT NAME,recovery_model FROM MASTER.SYS.databases where state = 0 ---只處理online的資料庫 and name not in ('tempdb','ReportServerTempDB','ReportServer') ----填寫不需要備份的資料庫 declare @databaseName nvarchar(128) declare @recovery_model int OPEN db_info fetch next from db_info into @databaseName,@recovery_model while @@fetch_status=0 Begin ---recovery_model 1 : FULL 2 : BULK_LOGGED 3:SIMPLE ---系統資料庫只全備 IF @backupType = 'F' SET @sqlCommand = 'BACKUP DATABASE '+ @databaseName +' TO DISK = '''+ @filepath_backup + ''+ @databaseName +'_Full_'+@dateTime+'.BAK'' with STATS = 10, INIT, COMPRESSION, CHECKSUM ' IF @backupType = 'D' and @databaseName not in ('master','msdb','model') SET @sqlCommand = 'BACKUP DATABASE '+ @databaseName +' TO DISK = '''+ @filepath_backup + ''+ @databaseName + '_Diff_' + @dateTime + '.BAK '' WITH DIFFERENTIAL, STATS = 10, INIT, COMPRESSION' IF @backupType = 'L' and @recovery_model <> 3 and @databaseName not in ('master','msdb','model') SET @sqlCommand = 'BACKUP LOG '+ @databaseName +' TO DISK = '''+ @filepath_backup + '' + @databaseName +'_Log_' + @dateTime + '.TRN'' with STATS = 10, INIT, COMPRESSION' print @sqlCommand EXECUTE sp_executesql @sqlCommand fetch next from db_info into @databaseName,@recovery_model End close db_info deallocate db_info PRINT '-- Backup completed successfully at '+convert(varchar, getdate(), 120) SET ANSI_WARNINGS ON END GO
備份作業
備份作業很簡單,就是調用存儲過程用計劃控製備份頻率
-- Author: KK -- Create date: 2016-09-27 -- Description: 備份資料庫,全備份每天一次 0點執行,差異備份6小時一次,日誌備份1小時一次 -- http://www.cnblogs.com/double-K/ --需要備份的資料庫未使用參數傳遞,而是選擇在存儲過程中指定,當添加新庫時不需要修改任何腳本 -- Parameter1: 備份類型 F=全部, D=差異, L=日誌 -------------------完整備份作業----------------- USE [msdb] GO /****** Object: Job [FULL_BACKUP] Script Date: 2016/9/30 12:13:12 ******/ BEGIN TRANSACTION DECLARE @ReturnCode INT SELECT @ReturnCode = 0 /****** Object: JobCategory [[Uncategorized (Local)]]] Script Date: 2016/9/30 12:13:12 ******/ IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) BEGIN EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback END DECLARE @jobId BINARY(16) EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'FULL_BACKUP', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'系統全備份', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'sa', @job_id = @jobId OUTPUT IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback /****** Object: Step [FULL_STEP1] Script Date: 2016/9/30 12:13:12 ******/ EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'FULL_STEP1', @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'[dbo].[sp_BackupDatabase] ''F''', @database_name=N'master', @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'EVERY_1d_zero', @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=20160930, @active_end_date=99991231, @active_start_time=0, @active_end_time=235959, @schedule_uid=N'813653e1-4128-4f47-b378-5a26b49085d0' IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id =