資料庫常常要做 "完整/差異" 備份,以下的語法是己撰寫好的應用語法,只要填入 JSON 內的資料,就可以做到輕易的資料庫備份應用。我採用的是 "預存程序" + JSON 的方法來達到可以備份資料庫,可以在 JSON 語法中去多做變化,來達到您的需求。
透過 IT邦幫忙 也給我記錄
IF OBJECT_ID('dbo.資料庫備份-快速執行資料庫備份') IS NOT NULL
DROP PROCEDURE [dbo].[資料庫備份-快速執行資料庫備份]
GO
CREATE PROCEDURE [dbo].[資料庫備份-快速執行資料庫備份]
(
@_InBox_JSON_Source nvarchar(Max) --資料來源
)
AS
-- 相關注解說明請寫在這裡,以免從 Visual Studio 轉至 SQL 說明內容沒有一起上去
-- ==========================================================================
-- 用 途:資料庫備份-完整備份
-- 製 作 人:
-- 年 月 日:
-- 說 明:這部份是給 API 應用
-- 1. 專業人員沒有寫註解不叫專業
-- 2. 請儘可能 FROM 後面加 WITH(NOLOCK) 不要鎖定表格
-- 3. 轉 JSON 格式 FOR JSON PATH, (輸出 Null)INCLUDE_NULL_VALUES, (排除 [] 格式)WITHOUT_ARRAY_WRAPPER
-- 4. 欄位不分大小寫 COLLATE Chinese_Taiwan_Stroke_CI_AS
-- ==========================================================================
-- ========宣告系統要用的資訊 - 開始 ================
DECLARE @_InBox_DataBaseName nvarchar(100) =JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name')
DECLARE @_InBox_BackName nvarchar(100) =JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_BackupFileName')
DECLARE @_InBox_BackMemo nvarchar(100) =JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_BackupMemo')
DECLARE @_InBox_BackupMethod nvarchar(100) =JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_BackupMethod')
DECLARE @_InBox_BackDate nvarchar(100) =REPLACE(CONVERT(nvarchar(30),GETDATE(),112),':','');
DECLARE @_InBox_BackTime nvarchar(100) =REPLACE(CONVERT(nvarchar(30),GETDATE(),8),':','');
DECLARE @_InBox_BackServiceName nvarchar(100) =@_InBox_BackName+@_InBox_BackTime
DECLARE @_InBox_DISK_DB_Path nvarchar(500) =JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory')+@_InBox_BackName+'_'+ @_InBox_BackupMethod +'_'+'DB_' +@_InBox_BackDate +'_'+@_InBox_BackTime+'.Bak'
DECLARE @_InBox_DISK_Log_Path nvarchar(500) =JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory')+@_InBox_BackName+'_'+ @_InBox_BackupMethod +'_'+'Log_' +@_InBox_BackDate +'_'+@_InBox_BackTime+'.Bak'
--回傳執行上的可能錯誤
DECLARE @_SystemInfoLog Table
(
DBName nvarchar(1000), --資料庫名稱
DBPathInfo nvarchar(1000), --儲存備份路徑
DBErrorMessage nvarchar(Max), --錯誤說明
Sysinfo_isError nvarchar(2) , --記錄錯誤的訊息
SysInfo_MainCode nvarchar(200) ,
SysInfo_MinorCode nvarchar(200)
)
-- ========宣告系統要用的資訊 - 結束 ================
if(LEN(@_InBox_DataBaseName)!=0 AND LEN(@_InBox_BackupMethod)!=0)
Begin
if(@_InBox_BackupMethod='完整')
Begin
--執行 Try
BEGIN TRY
--下達完整備份
BACKUP DATABASE @_InBox_DataBaseName
--========備份磁碟實際上的位置==========
-- 儲存檔案的位置
--==========================
TO DISK = @_InBox_DISK_DB_Path
--========備份方式==========
--完整備份 >> WITH NOFORMAT
--差異備份 >> WITH DIFFERENTIAL
WITH NOFORMAT,
--========壓縮方式==========
--檔案壓縮 >> COMPRESSION
--檔案壓縮 >> NO_COMPRESSION 檔案不壓縮
--==========================
COMPRESSION ,
--========備份作業覆寫========
--備份覆寫 >> INIT
--附加媒體 >> NOINIT
--==========================
NOINIT,
--========預設資料庫備份或還原的I/O=========
--預設為 >> 10
--==============================
BUFFERCOUNT = 1024,
--========此備份資料庫的名稱與說明 255 字以內=========
--預設為 >> 10
--==============================
NAME = @_InBox_BackMemo,
--========檢查媒體備份到期日====
--必須要檢查 >> NOSKIP 先檢查媒體中所有備份組的到期日
--不須要檢查 >> SKIP 則略過檢查動作
--==============================
SKIP,
--=====備份硬體-磁帶備份設定====
--釋放和倒轉磁帶 >> REWIND 將釋放和倒轉磁帶
--釋放和倒轉磁帶 >> NOREWIND 不釋放和倒轉磁帶
--==============================
NOREWIND,
--=====備份硬體-自動倒轉和卸載磁帶====
--釋放和倒轉磁帶 >> UNLOAD 自動倒轉和卸載磁帶
--釋放和倒轉磁帶 >> NOUNLOAD 磁帶機上保持載入
--==============================
NOUNLOAD,
--=====完成多少百分比時,回報一則訊息====
--預設為 >> 10
--==============================
STATS = 10
--填入記錄
INSERT INTO @_SystemInfoLog VAlues(
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name')+'-'+@_InBox_BackupMethod,
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory'),
'執行正常',
REPLACE(ERROR_STATE(),NULL,'0'),
'完整備份-成功',
'資料庫己確定完整備份了 ['+ JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name') +']'
)
END TRY
BEGIN CATCH
--填入記錄
INSERT INTO @_SystemInfoLog VAlues(
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name')+'-'+@_InBox_BackupMethod,
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory'),
ERROR_MESSAGE(),
REPLACE(ERROR_STATE(),NULL,'0'),
'完整備份-失敗',
'無法執行資料庫備份 ['+ JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name') +']'
)
END CATCH;
End
else if(@_InBox_BackupMethod='差異')
Begin
--執行 Try
BEGIN TRY
--下達查異性備份
BACKUP DATABASE @_InBox_DataBaseName
--========備份磁碟實際上的位置==========
-- 儲存檔案的位置
--==========================
TO DISK = @_InBox_DISK_DB_Path
--========備份方式==========
--完整備份 >> WITH NOFORMAT
--差異備份 >> WITH DIFFERENTIAL
WITH DIFFERENTIAL,
--========壓縮方式==========
--檔案壓縮 >> COMPRESSION
--檔案壓縮 >> NO_COMPRESSION 檔案不壓縮
--==========================
NO_COMPRESSION ,
--========備份作業覆寫========
--備份覆寫 >> INIT
--附加媒體 >> NOINIT
--==========================
NOINIT,
--========預設資料庫備份或還原的I/O=========
--預設為 >> 10
--==============================
BUFFERCOUNT = 1024,
--========此備份資料庫的名稱與說明 255 字以內=========
--預設為 >> 10
--==============================
NAME = @_InBox_BackMemo,
--========檢查媒體備份到期日====
--必須要檢查 >> NOSKIP 先檢查媒體中所有備份組的到期日
--不須要檢查 >> SKIP 則略過檢查動作
--==============================
SKIP,
--=====備份硬體-磁帶備份設定====
--釋放和倒轉磁帶 >> REWIND 將釋放和倒轉磁帶
--釋放和倒轉磁帶 >> NOREWIND 不釋放和倒轉磁帶
--==============================
NOREWIND,
--=====備份硬體-自動倒轉和卸載磁帶====
--釋放和倒轉磁帶 >> UNLOAD 自動倒轉和卸載磁帶
--釋放和倒轉磁帶 >> NOUNLOAD 磁帶機上保持載入
--==============================
NOUNLOAD,
--=====完成多少百分比時,回報一則訊息====
--預設為 >> 10
--==============================
STATS = 10
--填入記錄
INSERT INTO @_SystemInfoLog VAlues(
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name')+'-'+@_InBox_BackupMethod,
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory'),
'執行正常',
REPLACE(ERROR_STATE(),NULL,'0'),
'差異備份-成功',
'資料庫己確定差異備份了 ['+ JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name') +']'
)
END TRY
BEGIN CATCH
--填入記錄
INSERT INTO @_SystemInfoLog VAlues(
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name')+'-'+@_InBox_BackupMethod,
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory'),
ERROR_MESSAGE(),
REPLACE(ERROR_STATE(),NULL,'0'),
'差異備份-失敗',
'無法執行資料庫差異備份 ['+ JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name') +']'
)
END CATCH;
End
End
else
Begin
--填入指定的錯誤代碼
INSERT INTO @_SystemInfoLog VAlues(
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Name'),
JSON_VALUE(@_InBox_JSON_Source,'$[0].DB_Directory'),
'下達的命令與語法錯誤',
'0',
'0',
'0'
)
End
--轉出整個執行的內容
SELECT *
FROM @_SystemInfoLog
執行的語法動作
EXEC [資料庫備份-快速執行資料庫備份] '
[
{
"DB_Name":"資料庫完整的名稱",
"DB_Directory":"D:\\Microsoft SQL Server\\DataBack\\行政管理\\完整備份\\",
"DB_BackupFileName":"您要備份的檔案名稱",
"DB_BackupMemo":"針對此備份你要填入的說明",
"DB_BackupMethod":"完整/差異"
}
]'
要注意的部份
您可以配合 SQL Server Agent 來做排程來達到需求,備份出來的檔案會像是以下名稱
資料庫名稱_完整_DB_20181219_170916.Bak
資料庫名稱_差異_DB_20181219_170916.bak
請問我按照您的方式做了
出現完整備份,
然後再還原會去就掛了==>一直都顯示還原中
SQL 如下:
restore DATABASE DEMO_DB
from disk='D:\backup\DEMO_DB_完整__DB_20190701_154052.Bak'
with
move 'xxx' to 'D:\DemoDB\DMEO_DB.mdf',
move 'xxx_Log' to 'D:\DemoDB\DMEO_DB_log.ldf'
,NoRecovery
,Replace
go
您選擇還原的選項是什麼呢?? 我剛才直接用 "完整" 再還原到其他資料庫,還原是正常的.. 圖示的備份日期 今天 19:13 分備份再還原,備份失敗那你要看一下無法還原成功的原因是什麼??
你可以直接點選 X 的原因就可以知道了..
我是下SQL 指令:
restore DATABASE DEMO_DB
from disk='D:\backup\DEMO_DB_完整__DB_20190701_154052.Bak'
with
move 'xxx' to 'D:\DemoDB\DMEO_DB.mdf',
move 'xxx_Log' to 'D:\DemoDB\DMEO_DB_log.ldf'
,NoRecovery
,Replace
go
若是UI 操作的,錯誤
System.Data.SqlClient.SqlError: 備份組包含現有的 'OEE' 資料庫以外的資料庫備份。 (Microsoft.SqlServer.Express.Smo)
TITLE: Microsoft SQL Server Management Studio
------------------------------
Restore of database 'OEE' failed. (Microsoft.SqlServer.Management.RelationalEngineTasks)
------------------------------
ADDITIONAL INFORMATION:
System.Data.SqlClient.SqlError: The backup set holds a backup of a database other than the existing 'OEE' database. (Microsoft.SqlServer.SmoExtended)
For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&ProdVer=14.0.17254.0+((SSMS_Rel_17_4).180502-0908)&LinkId=20476
------------------------------
BUTTONS:
OK
------------------------------
我將NoRecovery 改成 Recovery 就好了
原來NoRecovery 是還要繼續還原...
restore DATABASE OEE
from disk='D:\DataBack\OEE\OEE_完整__DB_20190701_154052.Bak'
with
move 'OEE' to 'D:\OEE_DB\OEE.mdf',
move 'OEE_log' to 'D:\OEE_DB\OEE_log.ldf'
,Recovery
,Replace
go
喔...了解..
請問(星期一)做了完整備份 => OEE_完整DB_20190701_154052.Bak
今天(星期三)做了一個差異備份 => OEE_差異__DB_20190703_144614.Bak
上午試了完整備份。正常也沒有問題
那我怎樣差異備份,補上資料庫?
那你要看有沒有啟動 SQL Server Agent 呢?? 基本上我只要設定好,他就會自動備份 "完整與差異" 的動作
有個問題
0704做完整Backup
0705在做差異Backup
差異檔案比完整檔案 大?
在做個交易 更大?
有看了:https://blog.miniasp.com/post/2010/04/21/SQL-Server-Full-Differential-Transaction-Backup
觀念釐清:SQL Server 完整備份、差異備份、交易記錄備份
基本上,您的備份應該不太對!! 以我備份的經驗會是如下...
完整_DB_20190705_000001.Bak
差異_DB_20190705_003000.Bak
差異_DB_20190705_010000.Bak
差異_DB_20190705_010300.Bak
每天晚上 23:59:59 分鐘執行完整備份,每 30 分鐘差異性備份,所以我的檔案大概就會如上面的清單所列出來的,基本上如您並沒有設定連續的差異性備份檔案,那您可能要先看看您的設定有沒有錯誤了...
保哥的備份文章是 "理解備份觀念" ,但您的產生備份應該是設定上有錯誤...您再多試試...
所以不做交易備份
我想
星期天 : 完成備份
星期一 ~ 星期六: 每天做差異備份
每四小時做交易備份
喔...我是不太建議啦!! 完整備份我會每一天做一次,並且用外寫一支程式來對這些檔案進行 "以日期條件" 進行壓縮,那檔案的 Size 容量差很多。
以我的經驗,我的方法是比較保守一點。因為還原 "當天" 的備份必須要連同 "完整備份" 也要一併進行還原(你可以參考保哥的文章) 裡面有一段 "假設你想將資料庫還原到 2010/4/21 PM 9:00 的版本" 。還原資料會接續前面的備份,如果以你的方式,那你要將 "所有的備份檔案" 做為還原的檔案,那個數量真的是會差很多。
而且還原的時間會大一倍的時間,因為 "我認為以你的備份數量要還原到特定日期" 的資料,我會懷疑還原的回去嗎?? 每天一次的完整/差異備份就是提供在 "特定日期與時間內還原資料" 。 我是沒有做過以你的備份並還原的動作過,不然你自己試看看在不同的條件之下 "這樣子的備份是否符合你的需求"。
那我還覺得這樣子備份,還不如用 "資料庫鏡像和複寫 (SQL Server)" 的方法來處理,多複製一份資料到另一個資料庫,那可以做的事情更多..