Sql Server數據庫備份和恢復:原理篇


本文與您探討為什么Sql Server有完整備份、差異備份和事務日志備份三種備份方式,以及為什么數據庫又有簡單模式、完整模式和大容量日志模式這三種恢復模式。本文內容適用於2005以上所有版本的Sql Server數據庫 。

單就操作過程而言,Sql Server中數據庫備份和恢復過程是相當簡單的,可以通過Management Studio的圖形界面進行操作,也可以使用幾句T-SQL語句完成。但要明白備份恢復的整個過程,定制符合系統需求數據庫備份方案,卻需要知曉數據庫的實現原理。備份和恢復是數據庫的核心功能。

1 數據庫原理

本節簡要討論了Sql Server數據庫的存儲的物理和邏輯結構,這是備份恢復的理論基礎。

1.1 為什么使用數據庫

為什么要使用數據庫,而不是使用一個文件,然后自己寫一些方法來保存數據,那是因為使用數據庫我們就不用自己去實現下面這些算法上非常復雜的功能:

  • a.高效一致的結構化數據存取方法,進行復雜的任意條件組合嵌套的數據查詢(關系數據庫管理系統甚至為實現這一功能專門設計了一種語言:SQL)
  • b.保障數據操作的原子性和完整性
  • c.確保在服務器斷電、網絡中斷、服務器崩潰、客戶端崩潰的情況下,故障恢復后數據仍然是完整的
  • d.在服務器被完全物理摧毀的情況下,快速在新的服務器上使用遠程設備上的備份將數據恢復到災難發生之前的狀態
  • e.隨時將數據恢復到任意時刻或任意一個操作之前
  • ...

a 主要是功能和性能

bcde 四條都可以歸結為完整性。

數據庫系統的核心目標就是:在實現功能需求的基礎上,保證數據完整性和數據存取性能。

1.2 Sql Server存儲的物理結構和邏輯結構

1.2.1 如何實現完整性

經過很多理論研究和實踐,目前公認的最有效的實現完整性的方法是:將數據的存儲分為數據事務日志,在存取過程中使用來控制並發訪問。

數據是實時狀態。

事務日志記錄了數據發生變化的過程,對於數據庫數據的任何一個改變,都被作為一條記錄寫在了事務日志文件中。

事務是指一組操作要么全部成功要么全部不執行。

任何數據更改操作在寫入到數據文件中之前,必須先將更前后的數據寫入事務日志文件中,這樣當事務由於用戶取消、數據邏輯錯誤或軟硬件故障中斷時能夠正確的回滾或前滾到正確的狀態。

通過控制多用戶對同一數據的並發訪問。

這是事務系統最基本的原理,大多數關系數據庫系統和面向對象NoSQL數據庫系統都采用這種方法。

Sql Server也不例外,每個Sql Server數據庫由數據文件(*.mdf)和事務日志文件(*.ldf)構成。Sql Server包括了從行到表,從頁面到文件的各種粒度的鎖。

1.2.2 如何實現高性能

在計算機數據存取過程中,保障性能的算法最終都可以歸結為:索引和緩存。從實現層面到應用層面,Sql Server都在建立管理各種索引和各種緩存。

對於需要隨機存取的數據,分頁是最自然的索引方法,同時能夠方便的進行緩存,實現高效率的隨機存取。我們所熟悉的操作系統內存管理系統、文件管理系統都采用了分頁的方法。

在Sql Server中,對於數據文件mdf,主要是隨機存取,因此mdf以分頁的形式進行組織管理,每個頁面8KB。還進一步將8個相鄰的頁組成一個擴展,方便管理,類似Windows中的簇。

mdf中保存着多種類型的數據,包括表數據、索引數據和大塊數據等等。每個頁面只保存一種數據。

表中的每一條記錄都保存在一個表數據頁中,記錄不能跨頁,因此任何表中記錄的最大長度是略小於8KB(ntext之類的大塊列只計算引用的大小)的一個數值,略小是因為每個頁面需要一些空間來保存頁面自身的信息(頁頭)和記錄在頁面中的存儲位置。

在Sql Server中,對於事務日志文件ldf,主要是順序存取。在正常運行時,數據庫管理系統定期將日志順序寫入到ldf文件;在恢復時,順序讀取ldf文件。因此,日志文件不需要分頁,只要由一條條順序存儲的事務日志記錄構成即可。日志記錄也有緩存,定期寫入到ldf文件。

盡管數據庫系統是一個允許並發訪問的系統,但是對事務日志的寫入是串行化的,不可以並發,任何一個原子操作對應的事務日志記錄在事務日志文件中都有其唯一的位置,也就是唯一的事務日志記錄編號,這個編號是一直增大的,不會重復,越新的記錄編號越大,存儲位置也越靠后。

以上內容總結自Sql Server的產品文檔Sql Server Books Online,如有興趣可以在里面了解更詳細的內容。這些就是備份和恢復的基礎原理。

2 數據庫備份的實現

如前所述,數據文件mdf保存了數據的實時狀態,事務日志文件ldf記錄了數據庫中數據變化的過程。這個時候,我們要對數據庫進行備份,自然而然就有兩個選擇:

  1. 因為mdf文件中保存了數據庫中數據的實時狀態,那么我們只要把mdf文件拷貝一份就實現了當前時刻的數據庫備份。
  2. 既然ldf文件中保存了數據庫中數據變化的整個過程,那么我們就可以把這個ldf文件備份起來,然后用這些備份的事務日志記錄從頭重建整個數據庫,而且比至第一種方法,通過事務日志記錄恢復的方法可以將數據庫恢復到任一時刻。

實際上,Sql Server同時使用了這兩種方法。

2.1 拷貝數據文件:數據備份

籠統的說,數據備份很簡單,就是拷貝mdf文件。

但是如果數據庫特別大,比如幾十個G,將整個mdf文件拷貝一遍會占用大量的IO資源和磁盤空間。考慮到mdf文件內容是分頁保存的,而且數據庫中的數據在一定時間內不會全部發生變化,那么我們不必每次備份都把整個mdf文件都拷貝。只需要在每個頁的頁頭中設一個bit位記錄一下自從上次備份以來,這一頁是否有被修改過,那么,有了上次的備份,我們只需要把那些發生了變化的頁備份一下就可以。

這就是Sql Server中的完整備份差異備份

出於簡化設計和簡化備份恢復過程的考慮,雖然Sql Server在每個完整備份后面可以進行任意次的差異備份,但是所有的差異備份都是相對於最近一次完整備份的,而不是可能存在的上一次差異備份。

很自然的,任何差異備份之前必須有一次完整備份。

2.2 切割不斷變大的事務日志文件:事務日志備份

事務日志文件ldf記錄了數據庫中數據變化的過程。想象一下,數據庫中表的每條記錄不停的發生變化,而事務日志要記錄變化前和變化后的數據,如果一個數據庫的mdf文件有1G,那么它的ldf文件呢,非常有可能是幾個G。

對於頻繁發生數據修改的數據庫,事務日志文件ldf的增長是非常快的,到最后,比如若干年后,ldf文件很有可能是mdf文件的幾百倍大。

問題就出來了,記錄數據變化過程的文件將占居整個系統的絕大多數存儲空間,但是,卻用不到,因為我們真正頻繁訪問的是存儲當前數據的mdf文件。

這個時候,就要想辦法定期的將ldf中暫時用不到的很久以前的日志記錄轉移到其它存儲設備上。

這里要插一點,盡管現在的計算和存儲資源相對很廉價了,但是,在數據庫服務器上,計算和存儲都是相當昂貴的資源,原因有以下幾點:

  1. 現有關系數據系統多數不是分布式的,也就是單台服務器必須足夠強大,一台4路的服務器成本遠高於兩台2路的服務器,更多路的就屬於中大機了,成本更高。
  2. 用於存放數據庫文件的存儲往往采用的是SLC SSD之類昂貴的高性能服務器硬盤,而備份存儲就可以使用廉價的近線硬盤甚至磁帶機。
  3. 數據庫系統的軟件授權都是按CPU甚至按核來的,因此數據庫服務器上每個CPU、每個IO,每個存儲的成本不只是其硬件自身,還附帶了相對硬件更加昂貴的軟件授權。

因此,將數據庫服務器上大量存儲用在存放基本不用的ldf文件在成本上是不能被接受的。

到這里,你會明白,對於ldf文件,備份已經不只是為了防止服務器上ldf文件意外損壞才備份了,也是為了減小ldf的大小。

這樣,Sql Server中的事務日志備份就應運而生,而且一箭雙雕。

在Sql server中,事務日志備份將ldf文件中所有已經提交的事務的日志記錄備份出來,將其占用的ldf文件空間置為可用。

ldf本身分成很多邏輯段,事務日志記錄在邏輯段間循環存放,並可以根據需要擴大或收縮ldf文件。關於ldf的格式的詳細描述都可以在Books Online中找到。

2.3 恢復模式

或許你會說,過一定時間的事務日志我不要了,覆蓋就好,確實有這種需求的存在。但是同時,對於更多的生產用戶,系統完整的歷史日志是必須的,比如金融、國防以及大多數中大企業。

作為一個通用的產品,SqlServer考慮到了這兩個方向的需求。Sql Server提供了一種設置,稱為恢復模式來滿足這些不同的應用需求,包括三種:

簡單模式:就是不需要歷史事務日志記錄的模式,所有成功提交的事務的日志記錄都被標記為可覆蓋,該模式下的數據庫不能進行事務日志備份,只能進行完整備份和差異備份。那么,這個時候可以不要ldf了嗎?不可以,盡管不需要歷史的事務日志記錄,但是事務操作的完整性還是要保證的,這個時候ldf的作用主要就是實現事務。

很明顯的,除非數據庫執行過的某一個事務中包含了數量巨大的操作,否則,在簡單模式下,ldf文件會一直保持很小,因為它只要能存放得下一個事務中的所有操作的事務日志記錄就可以了。

完整模式:(請不要和完整備份中的完整混淆,兩者描述的是完全不同的東西)這一模式就是前面一直在描述的要記錄所有已提交的歷史事務日志記錄的模式,這也是大多數系統應用的模式。在這種模式下,ldf會隨着數據庫的運行不斷增大。在該模式下,可以進行完整備份、差異備份和事務日志備份三種備份。在故障發生時,可能還需要進行日志尾部備份,就是將最近一次事務日志備份之后到發生故障時刻的日志備份出來,以進行恢復。

大容量日志模式:這是完整模式下的一種可切換的模式。就是在完整模式下,如果要進行大量數據的批量操作,比如插入,可以切換到大容量日志模式,這時ldf只記錄整個批量操作的結果,而不記錄每個操作,可以減少不必要的ldf文件占用。當然恢復的時候,只能恢復整個批量操作,不能恢復到其中任意一個操作。應該只在需要批量操作的時候短暫的使用這一模式。

2.4 混合使用數據備份和事務日志備份

概括來說:數據備份有完整備份和差異備份兩種,事務日志備份就本身一種。

對於恢復模式為簡單模式的數據庫,只能進行數據備份,不能進行事務日志備份,數據庫發生故障時只能恢復到備份時刻,備份時刻到發生故障間的數據將丟失。

這里要講的是完整模式,這也是數據庫主要使用的模式。

理論上,有了事務日志,不需要數據備份也可以,因為我們可以從頭恢復嘛。但是有一個問題,那就是性能問題,從事務日志恢復數據相當於把數據庫創建以來所有的操作重新執行一遍,這將會消耗大量時間,對於運行很久的數據庫,這個時間可能會以天甚至月計,這明顯是不能接受的。銀行數據庫崩潰了,花幾天去恢復,若不是天朝的估計得倒閉。

這個時候,數據備份就有用了,對於完整備份,數據恢復就是簡單的文件拷貝,分分鍾鍾完成;對於差異備份,先進行最近一次完整備份的恢復,再執行差異恢復,只是頁的拷貝覆蓋,也是很快的。

這樣我們可以定期進行完整備份,比如每天凌晨0點執行一次完整備份,因為完整備份畢竟拷貝了整個數據庫,因此最好在業務不繁忙時進行,然后每6個小時進行一次差異備份,每隔20分鍾進行一次日志備份,日志備份是很快的,因為頻繁備份使得需要備份的日志一般都不大,而且日志文件本身是順序訪問文件,已提交的事務日志記錄都是只讀的,不會有寫操作,不涉及同步的問題,適合於頻繁備份操作。

這樣,當故障發生時,如果可能,先將日志的結尾進行備份。我們就可以先恢復最近一次完整備份,再恢復最近一次差異備份,然后再將跨越差異備份以及差異備份之后的所有事務日志備份連同結尾備份依次進行恢復,將數據庫在可接受的時間內完美恢復到發生故障的時刻。

通過以上分析我們也可以得知:

數據備份中,差異備份依賴於前一次完整備份,而各個完整備份之間沒有任何依賴關系。

對於事務日志備份,除了在事務日志備份之前必須有一次完整備份之外(這主要是為從簡單模式轉到完整模式的數據庫設計的),事務日志備份與數據備份完全獨立,兩者各進行各的。

每個數據備份中記錄了最后提交的事務日志記錄的編號,假設為N,在數據備份恢復完成后,接下來的事務日志備份恢復時,第一個事務日志備份只需要選擇包含了編號為N+1的事務日志記錄的備份文件就可以,然后依次選擇下一個事務日志備份文件,直到恢復到需要的狀態。Sql Server允許通過事務日志恢復操作將數據庫恢復到任何一個事務日志記錄編號或任何時刻。

3 總結 

 我們用一張表簡單總結一下:

  簡單模式 完整模式 大容量日志模式 備份的文件 可將數據庫恢復到
完整備份 可以 可以 可以 mdf 執行備份的時刻
差異備份 可以 可以 可以 mdf 執行備份的時刻
事務日志備份   可以 可以 ldf 備份涵蓋范圍內的任意時刻

本文描述了數據庫備份和恢復的基本原理,為進行實際的備份和恢復操作做好了理論准備。

在下一篇文章中將詳細討論Sql Server數據庫的備份和恢復操作,以及如何制定合理的備份方案。

另外,本文雖然是針對Sql Server編寫,但其原理適用於大多數關系數據庫管理系統。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM