SQL Server的備份有三種形式:
一是全備份(full backup)
這個備份裡麵包含的內容是值得商榷的,我們知道資料庫有兩種文件,數據文件與日誌文件,全備份是不是將所有的數據文件與日誌文件打包,備份成一個文件? 那麼還原的時候是不是需要做恢復,將備份過後發生的事務接著備份時間點重新執行一邊? 上面的問題細想都是肯定的。全備份做的事情,就是將所有的緩存先flush到磁碟上,不管在進行的事務是否提交,這樣保證了日誌的連續性,數據與日誌的一致性,如果事務沒提交 ,在日誌文件上的標記是active的,這段日誌也就不會被清空,下次恢復的時候,就從這段日誌開始,接著使用新的日誌執行。因此 全備份之前肯定會執行一次checkpoint;、
二是差異備份(differential backup)
這個備份會不會也重復full backup的過程,先執行checkpoint,然後再將上一次備份之後,發生數據頁變化的這些數據頁都備份起來,這部分備份就不會有日誌。但是和全備份一樣,備份的容積體量比較大,差異備份備份的是數據頁,不管這一頁是不是只有一條數據更改了,還是全部更改了;
三是日誌備份(transaction log backup)
日誌備份中需要注意的就是對未提交事務的理解,沒有提交的事務其實還是佔用日誌文件的VLF,shrink並不能回收日誌空間;提交事務的日誌如被備份之後,就會將日誌VLF打上unactive或者truncated標記,這個時候執行shrink就可以回收這部分日誌VLF了。日誌備份體量小,比較適合頻率高的執行,比如每5分鍾執行一次。
全備份:
全備份用到的命令,涉及到兩方面的參數,一是指定相應的備份設備,可以是磁碟,也可以是磁帶;另一方面 就是備份可用的選項,比如是否壓縮,是否加密。
BACKUP DATABASE database
TO backup_device [ ,...n ]
[ WITH with_options [ ,...o ] ] ;
備份設備很講究,可以事先定義好邏輯設備,也可以直接指定物理設備。磁帶備份機倒是沒見過,但是常規的磁碟備份還是可以討論一下的:
我們可以將一個本機帶路徑的物理文件名指定為備份設備:
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup.bck';
也可以將網路上的一個帶路徑的物理文件名指定為備份設備:
backup database AdventureWorks2012
to disk = '\BackupSystemBackupDisk1AW_backupsAdventureWorksData.Bak';
這里有個有趣的現象,如果我們在全備份之後 ,沒有備份好日誌,這個時候故障突然發生了,我們需要作恢復,但是恢復的時候因為會重寫日誌,這樣就會丟失數據,如果不採取額外地措施,系統是會報錯的:
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup.bck'
Msg 3159, Level 16, State 1, Line 6
The tail of the log for the database 「lenistest」 has not been backed
up. Use BACKUP LOG WITH NORECOVERY to backup the log if it contains
work you do not want to lose. Use the WITH REPLACE or WITH STOPAT
clause of the RESTORE statement to just overwrite the contents of the
log.
Msg 3013, Level 16, State 1, Line 6
RESTORE DATABASE is terminating abnormally.
所以如果對丟失的數據不關心或者認為不會丟失數據,可以採用with replace選項來重寫原來的日誌文件進行強制恢復。
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup.bck'
with replace;
差異備份:
差異備份相對全備份,優越的地方在於備份數據量少,但是有趣的是差異備份不能獨立存在(日誌備份也不能獨立存在,他倆只能依附於全備份,也就是說在執行差異備份和日誌備份的時候,必須先有一個全備份做好在那裡), 差異備份必須以一個全備份做基準,在這基礎之上再判斷哪些數據頁是有過更新的,這些更新的數據頁計算出來並被備份起來。
use master;
go
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup.bck';
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup.bck'
with differential;
假如我們沒有事先做好全備份,就直接作差異備份了,那麼這是不成功的:
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup2.bck'
with differential;
Msg 3035, Level 16, State 1, Line 11
Cannot perform a differential backup for database 「lenistest」, because
a current database backup does not exist. Perform a full database
backup by reissuing BACKUP DATABASE, omitting the WITH DIFFERENTIAL
option.
Msg 3013, Level 16, State 1, Line 11
BACKUP DATABASE is terminating abnormally.
日誌備份:
日誌備份相對差異備份來說,體量更小,同樣它也需要全備份事先存在:
backup log lenistestto disk = 'E:Data_BUlenistest5__backup.bck';
假如我沒有事先做好全備份,我們看看直接備份日誌會出現什麼結果:
Msg 4214, Level 16, State 1, Line 15
BACKUP LOG cannot be performed because there is no current database
backup.
Msg 3013, Level 16, State 1, Line 15
BACKUP LOG is terminating abnormally.
提示先做全備份!
備份我們都討論完了,接下來我們看看還原。還原通常有兩個步驟,一是還原,二是恢復。當然我們也可以直接還原不恢復,但是可能會丟失數據,除非全備份之後 ,沒有任何操作。假設我們一天一個全備份,每15分鍾做一個差異備份 ,每5分鍾做一個日誌備份,我們該如何還原我們的資料庫呢?
通常我們首先要知道我們的備份文件名或者物理路徑,這個地方涉及到很多術語很難理解,比如說backup device, backupset, backup media, media set ,media family.
MSDN上有一個解釋,先看這個腳本:
backup database AdventureWorks2012
to tape = '\. ape0'
, tape = '\. ape1'
, tape = '\. ape2'
with format
, medianame = 'MyAdvWorks_MediaSet_1';
解釋說到,這個備份操作產生了一個 media set, 這個media set就是命名為MyAdvWorks_MediaSet_1, 這個media set還有個media header, media header一旦生成,就可以往裡面寫入備份文件了。這段腳本也同時生成了一個橫跨三個tape的備份文件, 他們統稱為backup set.
當我們指定3個backup device作為backup set(備份集)並且執行第一次全備份的時候,接下來所有的備份都需要同時指定這3個backup device作為backup set:
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
with format
, medianame = 'lenistestbackupset';
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
with noinit
, differential
, medianame = 'lenistestbackupset';
Msg 3231, Level 16, State 1, Line 10
The media loaded on 「E:Data_BUlenistest5__backup01.bck」 is formatted
to support 3 media families, but 2 media families are expected
according to the backup device specification.
Msg 3013, Level 16, State 1, Line 10
BACKUP DATABASE is terminating abnormally.
上面我先作了一次全備份,指定了三個backup device作為一份backup set, 接下來作差異備份的時候,我只指定了其中兩個backup device作為backup set, 操作失敗,提示就是少了一個backup device.
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
with noinit
, differential
, medianame = 'lenistestbackupset';
這次我們指定了同樣個數的backup device,但backup device的順序顛倒了一下,操作成功。
到目前為止,我們的腳本已經新建了 1 個media set,名為 lenistestbackupset , 2 個backup set, 第一個backup set是全備份的backup set,另外一個backup set是差異備份。所以每一次備份都會產生一個backup set. Media set產生的時間則是第一次給資料庫作全備份的時候。
這個時候我們需要恢復資料庫,那麼第一步就是要先還原全備份,但是先不恢復,等全備份還原過後,再用差異備份做恢復:
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
with file = 1
, replace
, norecovery;
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
with file = 2
, recovery;
這里一定是用replace來重寫日誌。
select mf.media_set_id
, isnull(ms.name, 'no media name') as media_name
, mf.physical_device_name
, mf.family_sequence_number
, mf.media_family_id
, bs.database_name
, bs.backup_start_date
, bs.backup_finish_date
from backupmediafamily mf
inner join backupset bs
on mf.media_set_id = bs.media_set_id
left join backupmediaset ms
on bs.media_set_id = ms.media_set_id
where bs.database_name = 'lenistest';
上面的腳本可以抓出來這些media family, media set, backup set的信息,如果像上面的例子一樣, 我們用3個backup device來承載備份,那麼這3個backup device組成了一個media family, 按照family_sequence_number來編排,1,2,3。
下面實現一個備份到恢復的全過程例子,分別在full backup, differential backup, log backup之前各出入同樣的數據,看看是不是還原的時候,能正確還原過來:
insert into dbo.dataloading
(
object_id
, object_name
)
select object_id
, name as object_name
from sys.objects;
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
with format
, medianame = 'lenistestbackupset';
insert into dbo.dataloading
(
object_id
, object_name
)
select object_id
, name as object_name
from sys.objects;
backup database lenistest
to disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
with noinit
, differential
, medianame = 'lenistestbackupset';
insert into dbo.dataloading
(
object_id
, object_name
)
select object_id
, name as object_name
from sys.objects;
backup log lenistest
to disk = 'E:Data_BUlenistest5__backup01.bck'
, disk = 'E:Data_BUlenistest5__backup03.bck'
, disk = 'E:Data_BUlenistest5__backup02.bck'
with noinit
, medianame = 'lenistestbackupset';
接著我們做還原與恢復:
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup01.bck', disk = 'E:Data_BUlenistest5__backup03.bck', disk = 'E:Data_BUlenistest5__backup02.bck'
with file = 1
, replace
, norecovery;
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup01.bck', disk = 'E:Data_BUlenistest5__backup03.bck', disk = 'E:Data_BUlenistest5__backup02.bck'
with file = 2
, norecovery;
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup01.bck', disk = 'E:Data_BUlenistest5__backup03.bck', disk = 'E:Data_BUlenistest5__backup02.bck'
with file = 3
, recovery;
這里的file選項就是backup set選項,表示第一個備份集,第二個備份集,第三個備份集。如果想還原到最新的故障發生時間點,前面的restore都不能recovery,只有在最後的時候才能作recovery.
如果我們只想恢復全備份的數據,只要執行recovery就可以了,但是數據肯定是少了:
restore database lenistest
from disk = 'E:Data_BUlenistest5__backup01.bck', disk = 'E:Data_BUlenistest5__backup03.bck', disk = 'E:Data_BUlenistest5__backup02.bck'
with file = 1
, replace
, recovery;
2. sql2008怎麼備份日誌文件
一、 結尾日誌備份的含義。
由於結尾日誌備份是SQLServer資料庫特有的一個內容。所以對於從其他資料庫轉型過來的管理員可能並不了解這個結尾日誌備份的含義。在大多數情況下,如在完成恢復模式或者大容量日誌恢復模式下,SQLServer資料庫要求管理員備份事務日誌的結尾部分以獲得尚未備份的日誌記錄。這個在還原操作之前對日誌尾部執行的日誌備份就叫做結尾日誌備份。對於SQLServer資料庫來說,在事務日誌恢復之前進行事務日誌的尾部備份是非常必要的。因為結尾日誌備份作業可以防止用戶修改數據的丟失並最終確保日誌鏈的完整性。在利用事務日誌將資料庫恢復到某一個指定的點,如資料庫故障點的時候,結尾日誌備份是恢復計劃中的最後一個相關備份。如果在還原之前無法備份日誌的尾部,那麼就只能夠將資料庫恢復為故障發生之前創建的最後一個備份。而不能夠恢復到故障發生的那一點。所以說,結尾日誌備份對於SQLServer資料庫非常的重要。
二、 在何時該進行結尾日誌備份?
從結尾日誌備份的含義中,我們也可以看出,並不是在任何情況下都需要作結尾日誌備份。也就是說,對於SQLServer資料庫來說,並非所有的還原方案都需要執行結尾日誌部分。如在資料庫恢復的時候,不需要恢復到故障的那一點,就不需要進行結尾日誌備份。同理,如果先前的日誌備份中已經包含了恢復點,或者說管理員准備覆蓋某個資料庫或者移動資料庫的時候,往往不需要進行結尾日誌備份。另外需要的是,在某些特定情況下即使資料庫管理員想進行事務日誌尾部備份都不行。如當事務日誌文件已經損壞時就無法繼續進行事務日誌尾部備份。此時雖然資料庫管理員任人可以在不使用結尾日誌備份的情況下恢復資料庫,但是已經不能夠恢復到故障發生的那一點。也就是說,最新日誌備份後進行的任何數據修改工作與資料庫結構調整工作都回丟失。
具體的來說,如果遇到如下兩種情況,需要先對馬上對事務日誌進行尾部備份。
一是需要對資料庫進行還原操作,而且是要還原到最近到的一個點時,那麼需要先對資料庫進行事務日誌尾部備份。即在資料庫處於聯機狀態時,如果資料庫管理員需要對資料庫進行的下一個操走就是還原操作,那麼就需要在還原操作之前進行事務日誌尾部備份。也就是說,在還原操作之前才能夠進行事務日誌尾部備份,即在事務日誌備份備份與資料庫還原之間不能夠再進行任何的資料庫修改作業。否則的話在還原後這個修改會丟失。另外需要注意的是,為了出現一些不必要的錯誤,最好在備份事務尾部日誌的時候,採用NORECOVERY選項。這個選項主要是為了確保資料庫事務日誌尾部備份之後資料庫不能夠再被修改。也就是說,可以保證事務日誌尾部備份到資料庫還原中間的時間間隔之內,不再發生任何的資料庫更改作業。以確保在利用事務日誌尾部備份進行資料庫還原的時候,能夠還原到一個最近的時點。而不會有任何數據的丟失。這是在最正常的情況下對事務日誌的尾部進行備份。