本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/Rulition/archive/2009/10/17/4688982.aspx
/*
THIS4.0 數據庫備份腳本
[作者] Rulition QQ:7355157
2010年5月21日15:35:13 完成
2010年5月24日11:35:13 細節修改
2010年5月25日11:31:13 增加[完整備份]前的一致性檢查
2010年5月27日10:31:13 檢查差異備份的大小,避免過大文件影響差異備份.
2010年5月28日11:14:15 補備份時查看最近是否已做過完全備份.
[版本] v1.5
[環境] SQL2000 和 SQL2005 中測試通過
[說明]
利用雙機熱備的磁盤空間,將 THIS4.0 數據庫的備份計划設置為以下方式:
"差異備份"-每N小時執行一次,分別存儲到 1# 和 2# 的 D:\This_BackUp , 保留3天。
"完整備份"-晚上 00:30 和 12:30 及 17:30 各執行一次,存儲到 z$\This_BackUp,保留15天。
[特點]
1)備份頻度由 SQL 計划任務來調節
2)操作日志由 SQL 計划任務來收集 (詳見計划任務的高級選項)
3) 先刪除過期備份文件,然后再執行備份操作,與 SQL 操作模式相反
(也可以修改 (備份前的准備工作) 這一小節,與 SQL 操作模式一樣。)
4)自動判斷並建立備份文件夾、按保留時間刪除過期備份文件
5)在執行備份操作前,自動檢查空間是否夠用,自動回避[差異備份][完整備份]同時進行,並進行一致性檢查。
6)檢查差異備份的大小,避免過大文件影響差異備份.並自動做一次[完整備份]
[注意]
1)腳本中大量使用 MS-DOS 命令,如果不是很熟悉,請不要修改!
2)為刪除過期備份文件使用了 FORFILES.exe 命令,必須注明具體路徑,否則無法執行。
這個可以在 Win2000 環境下使用的命令,是 FORFILES v 1.1 - emmanubo@microsoft.com - 4/98
與 Win7 系統自帶的中文版,在使用參數上有一點區別,使用時請注意!
3)為減少操作日志大小,在 (一致性檢查) 這一小節調用了 isql.exe ,這個文件在 SQL2005 中沒有,
可以從 SQL2000 系統中拷貝過來,使用時注意路徑。
[參考]
1)清理系統備份日志、 刪除備份作業的歷史記錄
2)關於SQL2005 遠程備份
*以上資料詳見腳本最后一部分
exec usp_job_backup_this4
*/
CREATE Proc usp_job_backup_this4
(@Is_Run int = 0 ) ---- 當 @Is_Run = 1 時,自動執行所有操作,否則,顯示操作記錄。
AS
----
SET NOCOUNT ON
----
Select GetDate() AS '【開始時間】'
----Test
----Declare @Is_Run int
----Select @Is_Run = 0
----
/*參數設置*/
Declare @數據庫名 varchar(100)
Declare @備份路徑 varchar(100)
Declare @備份文件 varchar(100)
Declare @備份方式 varchar(10)
Declare @保留時間 varchar(10)
Declare @備份語句 varchar(1000)
----初值設置
Select @數據庫名 = 'THIS4'
Select @備份文件 = Convert(char(8),getdate(),112) + replace(convert(char(6),getdate(),108),':','')
----
/*完整備份-參數設置*/
If Convert(varchar,getdate(),24) between '03:00:00' and '04:00:00'
or Convert(varchar,getdate(),24) between '12:00:00' and '13:00:00'
---or Convert(varchar,getdate(),24) between '17:00:00' and '18:00:00'
Begin
Select @備份方式 = '完整備份'
Select @備份路徑 = '\\202.202.202.26\Z$\This_BackUp'
Select @備份文件 = @備份文件+'.bak'
Select @保留時間 = '10'
Print '【操作方式】' + '★' + @備份方式 + '★'
End
/*差異備份-參數設置*/
Else
Begin
Select @備份方式 = '差異備份'
Declare @備份路徑1 varchar(100)
Declare @備份路徑2 varchar(100)
Select @備份路徑1 = '\\202.202.202.22\D$\This_BackUp'
Select @備份路徑2 = '\\202.202.202.23\D$\This_BackUp'
Select @備份文件 = @備份文件+'.dif'
Select @保留時間 = '3'
Print '【操作方式】' + '★' + @備份方式 + '★'
End
----
/*提取上次備份的數據*/
Declare @backup_set_id int ----備份操作的ID號
Declare @backup_size numeric ----備份文件大小,其結果/1024才能與電腦看到的一致[單位:KB]
Declare @description nvarchar(510) ----備份描述
Declare @name nvarchar(256) ----備份名稱,后面跟上'_KB'+當時備份時的庫文件大小[單位:KB]
Select top 1 @backup_set_id = backup_set_id , @backup_size = isnull(backup_size/1024,1) ,
@description = [description] , @name = [name]
from msdb.dbo.backupset (NOLOCK)
where type = case when @備份方式 = '差異備份' then 'I' else 'D' end
and database_name = @數據庫名
order by backup_set_id DESC
----
If @備份方式 = '差異備份'
Begin
---切換@備份路徑
if @description = @備份路徑1+'\'+@數據庫名 Select @備份路徑 = @備份路徑2
if @description = @備份路徑2+'\'+@數據庫名 Select @備份路徑 = @備份路徑2
Print '【上次備份】' + @description
End
----
/*顯示操作信息*/
Print '【本次備份】' + @備份路徑 + '\' + @數據庫名
----
/*參數檢查*/
----
Declare @SQL nvarchar(4000)
---------------------------------------------------------------------------------------------
----判斷@數據庫名
if @數據庫名=''
Begin
Print('Error:請指定需要備份的數據庫')
Return
End
----判斷@數據庫名是否存在
Select @SQL = '
if not exists ( select name from master.dbo.sysdatabases where name=''' + @數據庫名 + ''' )
Begin
Print(''Error:指定的數據庫名無效,如有必要請注意大小寫!或運行 sp_helpsort 檢查 SQL Server 排序次序和字符集'')
Return
End
'
Exec (@SQL)
---------------------------------------------------------------------------------------------
----判斷@備份路徑
if isnull(@備份路徑,'')=''
Begin
Print('Error:請指定備份路徑!例如: E:\data.bak')
Return
End
/*開啟 xp_cmdshell 支持*/
Exec sp_configure 'show advanced options', 1
reconfigure with override
Exec sp_configure 'xp_cmdshell', 1
reconfigure with override
Exec sp_configure 'show advanced options', 0
reconfigure with override
----判斷自動建立相應文件夾
Select @SQL = ' if not exist ' + @備份路徑 +'\'+@數據庫名 + '\*.* md '+ @備份路徑 +'\'+@數據庫名 + '''' + ' NO_OUTPUT '
Declare @result int
Exec @result = xp_cmdshell @SQL , NO_OUTPUT
if (@result = 1)
Begin
Print('Error:指定的備份路徑無法使用!(有可能是訪問權限的問題)'+ @備份路徑 )
Return
End
---------------------------------------------------------------------------------------------
----判斷@備份文件
if ISNULL(@備份文件,1) = '1'
Begin
Print('Error:在獲取[@備份文件]時出現錯誤!'+ @備份文件 )
Return
End
/*備份前的准備工作*/
---------------------------------------------------------------------------------------------
----(10)獲取@備份路徑所在分區的剩余空間大小[已換成KB,近似值= 可用字節/1024*0.95 ]
Select @SQL=' dir '+ @備份路徑 + ' | find "可用字節" > "%temp%\Rulition" '
Exec xp_cmdshell @SQL , NO_OUTPUT
Exec xp_cmdshell ' for /f "tokens=3 delims= " %i in (%temp%\Rulition) do @echo %i > "%temp%\Rulition" ' , NO_OUTPUT
Select @SQL=' for /f "tokens=1-9 delims=," %1 in (%temp%\Rulition) do @echo %1%2%3%4%5%6%7%8%9 '
----將結果傳入到表[必須充許空值插入,否則會出錯!]
Create Table #disk_space (free_sizes VarChar(100) NULL )
Insert into #disk_space Exec xp_cmdshell @SQL
Delete from #disk_space where free_sizes is null
----提取結果
Declare @disk_space numeric
Select @disk_space = Convert(numeric,free_sizes)/1024*0.95 from #disk_space
Drop table #disk_space
---------------------------------------------------------------------------------------------
----(20)獲取當前數據庫大小(參考:sp_spaceused)[已換成KB,近似值= 統計結果/1024*0.95 ]
Select @SQL = ' Declare @dbsize bigint ' + CHAR(10) +
' Declare @logsize bigint ' + CHAR(10) +
' Declare @database_size bigint ' + CHAR(10) +
' Select @dbsize = sum(convert(bigint,case when status & 64 = 0 then size else 0 end)) ,'+ CHAR(10) +
' @logsize = sum(convert(bigint,case when status & 64 <> 0 then size else 0 end))' + CHAR(10) +
' from ' + @數據庫名 + '.dbo.sysfiles ' + CHAR(10) +
' Select (convert (dec (15,2),@dbsize) + convert (dec (15,2),@logsize) ) * 8192 '
----將結果傳入到表
Create Table #database_size (files_sizes dec(15,2) NULL )
Insert into #database_size Exec (@SQL)
----提取結果
Declare @database_size numeric
Select @database_size = Convert(numeric,files_sizes)/1024*0.95 from #database_size
Drop table #database_size
---------------------------------------------------------------------------------------------
----(25)一致性檢查
/*如果一致性檢查在白天進行時要花費很長時間,可以設置為只在晚上處理。(具體情況詳見操作結果日志)*/
If @備份方式 = '完整備份'
Begin
/*
在數據庫備份之前,應該進行數據的一致性檢查:
1。運行檢查點進程 checkpoint [強制將當前數據庫的所有臟頁寫到磁盤上。]
2。檢查數據庫 dbcc checkdb
3。檢查頁面 dbcc checkalloc
4。檢查系統表 dbcc checkcatalog
然后再進行數據庫備份。
----
【DBCC CHECKDB】 是大量占用 CPU 和磁盤的操作。每一個需要檢查的數據頁都必須首先從磁盤讀入內存。
另外,DBCC CHECKDB 使用 tempdb 排序。建議在服務器負荷較少的時候運行 DBCC CHECKDB。
如果在負荷高峰期運行 DBCC CHECKDB,那么事務吞吐量性能和 DBCC CHECKDB 完成時間性能都會受到影響。
----
【DBCC CHECKALLOC】 對數據庫中的分配和頁使用(包括索引視圖)情況進行檢查。
只用於向后兼容性的 NOINDEX 選項也適用於索引視圖。
如果已經執行 DBCC CHECKDB,則不必執行 DBCC CHECKALLOC。
DBCC CHECKDB 是 DBCC CHECKALLOC 的超集,除了對索引結構和數據完整性進行檢查之外,它還包括對分配進行檢查。
*/
----★一致性檢查[只保留檢查的最終結果到日志文件,注意修改 isql.exe 使用的用戶名和密碼還有 isql.exe 所在的路徑]★
Print '【一致性檢查】'
Declare @CHECK VarChar(1000)
----
Print '1.運行檢查點進程 (' + Convert(varchar,GetDate(),21) + ')'
if (@Is_Run = 1) CHECKPOINT
----
Print '2.檢查數據庫 (' + Convert(varchar,GetDate(),21) + ')'
Select @CHECK = 'D:\isql.exe -S '+ @@SERVERNAME + ' -d '+ @數據庫名 + ' -U sa -P SERVER -Q "dbcc checkdb (' + @數據庫名 + ') " -o "%temp%\check_db.log" -w 9999 & find "CHECKDB" "%temp%\check_db.log" '
if (@Is_Run = 0) Print @CHECK
if (@Is_Run = 1) EXEC xp_cmdshell @CHECK
----
Print '3.檢查頁面 (' + Convert(varchar,GetDate(),21) + ')'
Select @CHECK = 'D:\isql.exe -S '+@@SERVERNAME + ' -d '+ @數據庫名 + ' -U sa -P SERVER -Q "dbcc checkalloc (' + @數據庫名 + ') " -o "%temp%\check.log" -w 9999 & find "CHECKALLOC" "%temp%\check.log" '
if (@Is_Run = 0) Print @CHECK
if (@Is_Run = 1) EXEC xp_cmdshell @CHECK
----
Print '4.檢查系統表 (' + Convert(varchar,GetDate(),21) + ')'
Select @CHECK = 'C:\Progra~1\7-Zip\isql.exe -S ' + @@SERVERNAME + ' -d ' + @數據庫名 + ' -U sa -P SERVER -Q "dbcc checkcatalog (' + @數據庫名 + ')" '
if (@Is_Run = 0) Print @CHECK
if (@Is_Run = 1) EXEC xp_cmdshell @CHECK
----
Print '5.一致性檢查已完成 (' + Convert(varchar,GetDate(),21) + ')'
End
---------------------------------------------------------------------------------------------
----(30)刪除過期備份文件
---- 凡大於(@保留時間)24小時的都會被刪除,注意擴展名!!
---- forfiles.exe 也要指定路徑,否則無法執行這個操作.
Declare @刪除操作 nvarchar(4000)
----
Select @刪除操作 =' pushd ' + @備份路徑 + '\' + @數據庫名 + ' && ' +
' d:\forfiles.exe -M'+@數據庫名+'_*.bak -c"cmd /c echo 刪除 @FILE & del @FILE " -D-'+ @保留時間 + ' && ' +
' d:\forfiles.exe -M'+@數據庫名+'_*.dif -c"cmd /c echo 刪除 @FILE & del @FILE " -D-'+ @保留時間 + ' && ' +
' popd '
Print '【刪除文件】 保留時間: ' + @保留時間 + ' 天'
if (@Is_Run = 0) Print @刪除操作
Exec xp_cmdshell @刪除操作---- , no_output
---------------------------------------------------------------------------------------------
----(40)備份可行性估算
---- 如果 [剩余空間] 不夠存放 [預期備份]的大小,先刪除過期備份文件,如果還不夠用,則退出。
---- [預期備份的大小] = [上次備份文件的大小] / [上次備份時數據庫的大小] * [當前數據庫的大小]
---- SQL的備份策略是先備份后刪除,事先也不判斷一下,很浪費時間。
----
----[上次備份時數據庫的大小]取自 msdb.dbo.backupset.name ,在生成備份語句時進行標記。
----
Declare @last_data_sizes numeric
Declare @評估結果 varchar(8)
----
Select @last_data_sizes = 1
Select @評估結果 = '通過'
----如果上次備份時沒有'_KB'標記,則默認為1。
if ( CharIndex('_KB',@name) = 0 ) Select @last_data_sizes = 1
else
Begin
----如果僅有'_KB'標記,但沒有數據,也默認為1。
if ( CharIndex('_KB',@name) + 3 ) > LEN(@name) Select @last_data_sizes = 1
----否則,提取'_KB'后的數據
else Select @last_data_sizes = Convert(numeric,SubString(@name,CharIndex('_KB',@name)+3,20))
End
----評估情況明細
if (@Is_Run = 0)
Begin
Print '【評估情況】'
Select @backup_set_id as '上次備份的ID: '
Select isnull(@backup_size,1) as '上次備份文件的大小(KB)' , isnull(@last_data_sizes,1) as '上次備份時數據庫的大小(KB)'
Select @database_size as '當前數據庫的大小(KB)' , @disk_space as '可用磁盤空間(KB)'
Print '【本次備份】' + @備份路徑 + '\'+ @數據庫名
End
----開始評估
----如果[上次備份文件的大小] = 1 , 則比較 [當前數據庫的大小]*0.80 與 [可用磁盤空間]
----這里的 (*0.80) 是人個經驗值,可以結合每次的【評估情況】大致算出來.
if @last_data_sizes = 1
Begin
if @database_size * 0.80 > @disk_space
Begin
Select @備份路徑 + ' 可用磁盤空間不足,無法存入數據庫備份文件,退出操作!' + CHAR(10) as '【錯誤提示1】'
Return
End
End
----[預期備份的大小] = [上次備份文件的大小] / [上次備份時數據庫的大小] * [當前數據庫的大小]
else
Begin
if ( @backup_size / @last_data_sizes ) * @database_size > @disk_space
Begin
Select @備份路徑 + ' 可用磁盤空間不足,無法存入數據庫備份文件,退出操作!' + CHAR(10) as '【錯誤提示2】'
Return
End
End
----檢查差異備份的大小
----如果 [上次備份文件的大小] 相對 [當前數據庫的大小] 超過 30% ,說明上次的完全備份失敗了,與此同時,最近又沒有做過完整備份,
----則必須再次進行完整備份,否則,數量過多的大體積差異備份文件會占用對應的磁盤空間,造成差異備份的失敗.
----這里的 (超過 30%) 是人個經驗值,可以結合每次的【評估情況】大致算出來.
If( @備份方式 = '差異備份' and ( @last_data_sizes <> 1 ) )
Begin
if (isnull(@backup_size,1) / @database_size > 0.3)
if NOT EXISTS (Select 1 from msdb.dbo.backupset where type = 'D' and backup_set_id > @backup_set_id and [name] like '%' + @數據庫名 + '%' )
Begin
Print '【有情提示】' + '上次(差異備份)的文件偏大,有可能最近一次的完整備份失敗!現在改為【完整備份】進行補救。'
Print '【有情提示】' + '如果多次出現這個問題,請檢查相關所有操作或設置。'
Select @備份方式 = '完整備份'
Select @評估結果 = '失敗'
Select @備份文件 = Replace(@備份文件,'.dif','.BBF') ----將后綴名改為:.BBF (補備份)
End
End
----
if @評估結果 = '通過' Print '【評估通過,可以備份!】'
---------------------------------------------------------------------------------------------
/*組織@備份語句*/
Select @備份語句=''
Select @備份語句='BACKUP DATABASE '+ @數據庫名 + ' TO DISK = N''' + @備份路徑+'\'+@數據庫名+'\'+ @數據庫名 + '_' +@備份文件 +
''' WITH RETAINDAYS = ' + @保留時間 + ', NOFORMAT, NOINIT, NAME = N''' +
@數據庫名 + '_' + @備份方式 + '_' + @備份文件 +'_KB' + Convert(varchar,@database_size) +
''', SKIP, NOREWIND, NOUNLOAD, STATS = 100,'
+ ' DESCRIPTION = '''+ @備份路徑 + '\' + @數據庫名 +''''
----
If @備份方式 = '差異備份' Select @備份語句 = @備份語句 + ' , DIFFERENTIAL '
----
/*顯示@備份語句*/
Print '【備份語句】'
Print @備份語句
----
/*[差異備份]回避[完整備份]*/
if exists(select spid from master.dbo.sysprocesses where db_name(dbid) = @數據庫名
and status = 'runnable' and cmd= 'BACKUP DATABASE')
Begin
Print @數據庫名 + ' 正在備份,跳過本次操作!'+ CHAR(10)
Return
End
----
/*執行操作*/
if (@Is_Run = 1) Exec (@備份語句)
----
Select GetDate() AS '【結束時間】'
----
/*
[參考資料1]
----清理日志記錄
Select * from msdb.dbo.backupset
Select * from msdb.dbo.restorehistory
----
刪除備份和還原歷史記錄表中所有早於指定日期的備份集的條目。
由於執行備份或還原操作后會在備份和還原歷史記錄表中添加一些行,
因此使用 sp_delete_backuphistory 可以減小 msdb 數據庫中歷史記錄表的大小。
----
Declare @dt datetime
Select @dt = cast(N'05/01/2010 00:00:00' as datetime)
exec msdb.dbo.sp_delete_backuphistory @dt
----刪除作業的歷史記錄
EXEC msdb.dbo.sp_purge_jobhistory @oldest_date='05/01/2010 00:00:00'
EXEC msdb..sp_maintplan_delete_log null,null,'05/01/2010 00:00:00'
[參考資料2]
關於 SQL2005 遠程備份
Rulition 10:19 2009-10-17
要實現 SQL 遠程備份,必須處理好本機遠程訪問的問題:
第一、遠程計算機與本機最好在同一網段內,如果跨了網段(或VLAN),需交換機路由支持,甚至修改本地路由表。
第二、為本機提供 SQL 服務的“用戶名”和“密碼”必須是[遠程計算機]的[合法用戶],且能對[遠程計算機]的[備份文件夾]進行[完全操作]。
一般情況下,在安裝 SQL 服務時使用的是系統帳戶(多半是 administrator),如果剛好是遠程計算機的合法用戶,則處理起來就簡單多了。
否則,在進行遠程備份時必須使用 xp_cmdshell 調用 MS-DOS 的 net use 命令,使用對方的[合法用戶]進行登記,以操作[備份文件夾]。
第三、至於[遠程計算機]的[備份文件夾],可以事先在[遠程計算機]上將[備份文件夾]進行共享,並指定可完全訪問的用戶名。
如果不想讓無關的人看到這個[備份文件夾],可在共享時將共享名后加上$,例如:備份文件夾$
或者,在使用 net use 進行[合法用戶]登記時,直接使用對方超級用戶,這樣可直接訪問[備份文件夾]。
例如:\\COMPUTER\E$\備份文件夾
net use \\COMPUTER\E$\備份文件夾 /user:用戶名 口令
如果是空口令,可用""代替: /user:用戶名 ""
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/Rulition/archive/2009/10/17/4688982.aspx
*/