觀念釐清:SQL Server 完整備份、差異備份、交易記錄備份

  分享到噗浪!

我之前一直認為 SQL Server 完整備份會截斷交易記錄,其實不然,昨天與 德瑞克 稍微聊了一下也就此釐清了長久以來的錯誤觀念,雖然這點小東西影響不了日常的備份作業,但對於 SQL Server 備份觀念的釐清也會對資料庫還原時更有信心,今天為了驗證觀念正確也做了一些小實驗,以下是一些關於 SQL Server 備份還原的觀念整理與心得筆記。

完整備份

  • 同時會備份 資料檔 ( *.mdf ) 與 交易記錄檔 ( *.ldf )
  • 要做任何差異備份交易記錄備份之前,一定要做一次完整備份

差異備份

  • 只會備份 資料檔 ( *.mdf ),但僅有最近一次完整備份備份當下這段時間所異動的資料
  • 差異備份不會備份任何交易記錄檔,備份的內容只會拿目前資料檔最近一次完整備份的資料內容做差異比對

交易記錄檔備份

  • 只會備份 交易記錄檔 ( *.ldf )
  • 若透過 SSMS 操作,在預設的情況下會自動截斷交易記錄
  • 交易記錄備份的 紀錄序號 (LSN) 是從資料庫建立開始就一直連貫的

 

如何證明上述觀念正確?

透過查詢 msdb 的 backupset 系統資料表可以查詢出所有 備份組 (backupset) 的備份歷史紀錄,請參考以下 T-SQL 語法:

SELECT 
	a.[database_name] as '資料庫名稱',
	CASE a.[type]
	WHEN 'D' THEN N'資料庫'
	WHEN 'I' THEN N'差異資料庫'
	WHEN 'L' THEN N'紀錄'
	WHEN 'F' THEN N'檔案或檔案群組'
	WHEN 'G' THEN N'差異檔案'
	WHEN 'P' THEN N'部分'
	WHEN 'Q' THEN N'差異部分'
	ELSE N'NULL'
	END as '備份類型',
	a.[first_lsn] as '備份組中第一個LSN',
	a.[last_lsn]  as '備份組之後下一個LSN',
	a.[database_backup_lsn] as '最近的完整資料庫備份之LSN',
	a.[differential_base_lsn] as '差異備份的基底 LSN',
	a.[backup_finish_date] as '備份完成的日期和時間'
FROM
	msdb..backupset a INNER JOIN master..sysdatabases b ON 
	a.database_name COLLATE DATABASE_DEFAULT 
       = b.name COLLATE DATABASE_DEFAULT 
ORDER BY
	a.database_name, a.backup_finish_date

透過下圖執行結果 (點圖可放大),很容易能理解備份時交易記錄的連貫特性:

第一次交易記錄備份時的備份組中第一個或最舊的紀錄序號(LSN)是一致的,代表交易記錄備份是從整個資料庫的「第一筆交易資料開始備份」:

接著我們再看看該資料庫所有交易紀錄備份的中 LSN 完全是連貫的,所以完整備份差異備份都不會影響交易記錄備份的 LSN 連慣性:

 

資料庫如何依序還原?

基本上 SQL Server 有能力將資料庫的資料還原到任何一個資料庫備份的時間點,假設你每一分鐘備份一次交易記錄的話,若你的資料庫發生毀損,透過這些備份資料還原最多只會遺失 1 分鐘以內的資料,如果你想還原到 3 天前的特定時間,也可以透過交易記錄備份還原到特定的備份時間點。

由於交易記錄備份的 LSN 不會中斷的關係,你甚至可以從第一次完整備份開始逐一將交易記錄還原到任意時間點 (使用 RESTORE 可以搭配 STOPAT | STOPATMARK | STOPBEFOREMARK 等參數來還原),但若資料庫存取量非常大或資料庫已運行多年,可能會導致交易記錄備份檔非常佔據硬碟空間,從實務上來講通常不會保留這麼完整的交易記錄備份,但對於資料完整性非常要求的單位(如:金融業)就有可能被要求要保留完整的交易記錄資料。

為了加快資料還原的速度,我們通常不會從第一次完整備份開始逐一將交易記錄備份檔還原,而會透過最近一次的完整備份檔來還原資料庫,甚或透過完整備份與差異備份的機制縮短交易記錄備份還原的時間,一般來說有以下幾種資料還原策略:

完整備份還原 –> 交易記錄備份還原

  1. 先還原完整備份
  2. 再還原完整備份後所做的交易記錄備份

完整備份還原 –> 差異備份還原 –> 交易記錄備份還原

  1. 先還原完整備份
  2. 再還原差異備份
  3. 再還原差異備份後所做的交易記錄備份

備註:只要交易記錄備份的紀錄序號能夠連貫,SQL Server 就可以透過交易記錄備份還原資料。

以下是一個實務上常用的資料庫備份策略:

  • 每月第一天執行一次完整備份 ( AM 3:00 )
  • 每個星期天執行一次差異備份 ( AM 4:00 )
  • 每 15 分鐘執行一次交易記錄備份

假設你想將資料庫還原到 2010/4/21 PM 9:00 的版本,你就必須會用以下順序還原資料庫:

  • 利用 2010/4/1 AM 3:00 的完整備份還原資料庫
  • 再還原 2010/4/18 (日) AM 4:00 的差異資料備份
  • 再還原所有 2010/4/18 (日) AM 4:00 之後做的的交易紀錄備份

還原時的注意事項:

還原的過程中在最後一個備份檔還原之前都必須保持 不回復為認可的交易 (NORECOVERY) 的狀態:

 

關於查詢所有 備份組 (backupset) 的備份歷史紀錄,以下是較完整的 T-SQL 語法,相關欄位可以參考《Microsoft SQL Server 線上叢書》對於 backupset (Transact-SQL) 的說明:

SELECT 
	a.[database_name] as '資料庫名稱',
	CASE a.[type]
	WHEN 'D' THEN N'資料庫'
	WHEN 'I' THEN N'差異資料庫'
	WHEN 'L' THEN N'紀錄'
	WHEN 'F' THEN N'檔案或檔案群組'
	WHEN 'G' THEN N'差異檔案'
	WHEN 'P' THEN N'部分'
	WHEN 'Q' THEN N'差異部分'
	ELSE N'NULL'
	END as '備份類型',
	a.[name] as '備份組的名稱',
	a.[first_lsn] as '備份組中第一個或最舊的記錄序號',
	a.[last_lsn]  as '備份組之後下一個記錄的記錄序號',
	a.[database_backup_lsn] as '最近的完整資料庫備份之記錄序號',
	a.[differential_base_lsn] as '差異備份的基底 LSN',
	a.[backup_finish_date] as '備份作業完成的日期和時間',
	a.[backup_size] as '備份組的大小 (以位元組為單位)'

FROM
	msdb..backupset a INNER JOIN master..sysdatabases b ON 
		a.database_name COLLATE DATABASE_DEFAULT = 
		b.name COLLATE DATABASE_DEFAULT 
ORDER BY
	a.database_name, a.backup_finish_date

心得分享

其實我對 IT 工作一直有個體悟,由於我們不可能看完所有 MSDN 或 TechNet 文件,看過也不一定會記得,所以有些工作就算你真的在實務上知道怎麼做也不見得自己理解的觀念是對的,所以保持著一顆虛懷若谷的心還真的蠻重要的,不過該有自信的時候千萬不要畏縮!

像在我們公司的工作環境裡隨時充滿著挑戰,每個人隨時都可以挑戰你的觀念,連老闆也不例外,挑戰成功可能還有意外驚喜,例如有免費中餐之類的 XD,如果有邏輯說不通的、理論與實務不符的地方、沒效率的作法、無法清楚表達的抽象概念、……等等,雖時都可以提出自己的看法與意見,為了追求技術的真理我們毫不手軟,所以在公司內部我也經常與同事討論、甚至是辯論一些大家看法不太一致或不太確定的地方,為的就是讓每個人對於特定知識的抽象概念能有一致且正確的理解,另一方面也是加強初學者的自信心,因為無法理解抽象概念的人講話永遠比較小聲,當理解前因後果來龍去脈之後就會慢慢展現自信,相對的工作出錯的機率也會降低!

相關連結

此文章由 will 發表於 2010/4/21 下午 12:46:00

永久連結 | 評論 (13) | 此文章的RSSRSS comment feed |

分類: SQL Server | 心得分享

標籤: ,

評論

二月 16. 2011 11:20

jerrymow

保哥您好,
依您上述 differential 是備份 mdf,transaction log 是備份 ldf,
log 每隔15分鐘做一次備份

那假設在 01:00 同時做了 differential 跟 log 的備份
在還原時 0100 的那份 log backup 還需要還原嗎?

若把 0100 的那份 log backup 還原,會不會導致反而不一致?

Jerrymow

jerrymow Taiwan

二月 16. 2011 13:52

Will 保哥

jerrymow: 如果你真的確定是同一個時間點做備份,你還原差異備份即可。如果不確定而又要精準還原的話,可以分析交易記錄的 LSN 範圍是否介於差異記錄的「備份組之後下一個LSN」這個數字中間,如果是的話,就代表你還要額外還原交易記錄,這樣資料才會完整。

實務上來講,我們不會讓同一個時間點執行差異備份與交易記錄備份。

Will 保哥 Taiwan

四月 24. 2011 00:14

Max0214

受益良多,謝謝分享~

Max0214 Taiwan

七月 31. 2011 19:10

lamihsuen

感謝分享,讓我了解,完整備份,差異備份,交易記錄備份 的觀念雖然我還不會 T SQL 語法
現在我更深入了解資料備份觀念

lamihsuen Taiwan

九月 28. 2011 10:44

Tomy

若要做Log shipping 時,仍用此備份機制或有所不同?

Tomy Taiwan

九月 30. 2011 00:16

Will 保哥

Tomy: 是的,做 Log Shipping 的過程中也會做「交易記錄備份」,所以原本的維護計畫如果也有交易記錄備份的話,必須將其停用,否則會出問題。

Will 保哥 Taiwan

十二月 8. 2011 20:39

Yu

保哥,我可不可以請教你
有關於SQL相關的問題,我一直在看保哥寫的例子,但我還是不懂,不知道方不方便請保哥有什麼解決方法或建議的。
以下是有關於我的問題....
使用平台MS SQL 2005
Database name: InterChan
Table name: Transactions

在InterChan database 中有個Transactions table,由於每年的資料量很大,現在要寫一個Stored Procedures,
每天要要將此Table 資料備份要另一個Database中相同的名稱Transactions table,要確保資料已備份到後,
再刪除原本的資料,但新的Database 要按照年份來分,如:2011年database name 即為:InterChan2011,
Table 名稱一樣是用Transactions即可。

在備份時若Database 不存在時,要自動Create database及table

P.S.請利用sys.databases確認database是否存在,Sys.Columns, Sys.Types, Sys.objects來判斷table 的欄位及型態。

Yu Taiwan

二月 20. 2012 11:15

振銘

我的備份計畫是

每天完整備份一次
每十五分鐘 備份一次交易紀錄

我的疑問是 我把第一次的交易紀錄刪除 會不會影響

我在第四天 要還原 第三天的 16:15分 資料庫作業@@?

振銘 Taiwan

二月 20. 2012 14:07

Will 保哥

振銘: 你只要有第三天凌晨的完整備份,加上該次完整備份之後所有的交易記錄備份,就能夠還原到第三天 16:15 分的資料。

Will 保哥 Taiwan

二月 20. 2012 14:29

振銘

謝謝^^ 這樣我就了解了!

振銘 Taiwan

五月 6. 2012 22:08

小豆

保哥~你好唷~
在SQL2008上,試著做備份的時候,遇到了幾個個問題,不知道保哥可不可以給我一些方向呢?謝謝~~。

1. 完整備份和差異備份,都選了覆寫,然後,同時指向同一個bak檔,結果在還原的時候,出現錯誤:「無法還原記錄或差異備份,因為沒有可向前復原的檔案」

2. 還原時,同時選擇了完整備份+交易記錄檔,選項並選擇了「NORECOVERY」,完成復原後,每次資料庫都會呈現「正在還原」的文字,若選擇第一個選項「RECOVERY」,則可以順利作復原的動作。

3. 在備份的時候,看到有一個選項「備份組逾期的時間」,設定了5天,但是5天後,還原時,還是可以看到5天前的備份檔案,不曉得,是不是我使用錯了呢?因為只想保留1個星期交易記錄檔。

小豆 Taiwan

五月 6. 2012 22:14

Will 保哥

小豆: 你可能對 SQL Server 的備份觀念沒有十分清楚,建議你先看一下以下文章:

SQL Server 資料庫的備份與還原
msdn.microsoft.com/zh-tw/library/ms187048.aspx


資料可能有點多,但建議你耐心看完,這樣對你建立完整的 SQL Server 資料庫備份還原觀念會很有幫助。

Will 保哥 Taiwan

五月 7. 2012 09:29

小豆

保哥~~謝謝你~~

小豆 Taiwan

新增評論


( 您輸入的Email不會顯示於網站上 )

  Country flag

biuquote
  • 評論
  • 線上預覽
Loading