2017年2月19日 星期日

SQL SERVER 差異備份的解析

差異備份是以上次完整備份為基底,將到目前的差異備份出來。大多數人的問題或許跟我一樣:「系統如何比對上次完整備份到現在有哪些差異?」。
SQL SERVER是以8K 為一個Page,這是SQL SERVER的最小儲存單位;而每8個連續的page則組成一個 「Extent」。ExtentSQL SERVER空間管理的最小單位。
每一個資料檔案(mdf/ndf)都是由多個extent所組成。為了管理及紀錄這些extent的狀態。SQL SERVER的每個資料檔中,有一些系統的頁面,如GAMSGAMPFSIAM…等。透過這些頁面,來紀錄資料檔中的頁面情況。






在這些系統的頁面中,有一個稱為DCMDifferential Changed Map)的頁面,每個資料檔至少有一個DCM頁面,它位於每個資料檔的第6頁(頁面編號從0起算)。
一個DCM頁可以保存63904extent狀態訊息。每個DCM蓋了每個GAM的範圍。因此每隔511232頁,DCM會重複一個。第2DCM頁會出現在第511238頁。

DCM是以bitmap的方式,來紀錄每個extent是否有過異動(0:未異動,1:有異動),當執行差異備份時,系統透過讀取DCM頁,來獲得哪些extent有異動,並備份那些有異動的extent,以完成差異的備份。但每次差異備份完,系統並不會去更改DCM的值,因此後續的差異備份動作,將會涵蓋之前的差異備份資料。

所以,差異備份的效能跟資料庫大小無關。差異備份的效能跟期間內的異動量相關。

差異備份實際測試
首先我們建立一個新的資料庫,並觀察它的DCM
create database TESTBAK
go
dbcc traceon(3604)
dbcc page(TESTBAK,1,6,3)


















上述顯示的結果中,(1:0) 代表檔案編號1的第0頁。Extent並沒有所謂的ID來識別。通常以該extent的第1頁,來做為extent的識別碼。因此(1:0),代表了第一個 extent,它包含了頁面編號1:0 ~ 1:7。至於CHANGEDNOT CHANGED,則表示了這些extent是否有被異動過 。

依上面的解釋,我們可以從上圖dbcc page的結果,計算出這個DB共有65extent
(512-0/8)+1 =65 (這個編號1的資料檔,共有65extent

當然,我們也可以直接用 dbcc showfilestats來查詢












接著,我們先對資料庫進行一次全備份,並再以dbcc page觀察DCM的情況
backup database TESTBAK to disk='c:\test\testbak.bak'
go
dbcc traceon(3604)
dbcc page(TESTBAK,1,6,3)

















可以看到執行全備份後,DCMbitmap有變化,大多數的DCM bit被變更為0(亦即NOT CHANGED),因為這些extent已經被備份了。
但或許你會覺得奇怪「全備份完後,不是所有的頁面應該都要標識成 NOT CHANGED才對,為什麼還是有些extent的狀態是CHANGED(已異動)」?
那是因為每次備份完成後,SQL Server會將有關該備份的訊息存儲在一些系統TABLE中。這會導致部分頁面在備份完後立即被更改,因此你永遠不會看到完全為(NOT CHANGED)的DCM

DCM頁,Slot 1 offset 0xbe用於儲存bitmap,長度7992 bytes,扣除前4bytesrecord meta data。共有63904bits可以用來存放extent的資訊。從頁頭0起算第194byte開始,即為DCM bitmap
為了再詳細的了解DCM,我們再次使用dbcc pageDCM頁的二進位資料顯示出來,跟上面的圖做一個比對。

dbcc page(TESTBAK,1,6,2)
















上圖dbcc結果,DCM bitmap0701…..開始。
DCM的解讀,要一個個byte來看:
例如
第一個byte0x07=00000111 
從右邊開始看,每個bit代表一個extent的狀態。因此00000111,表示第1-3extent,是CHANGED。第4-8extentNOT CHANGE。如下表示:
(1:0) CHANGED
(1:8) CHANGED
(1:16) CHANGED
(1:24) NOT CHANGED
(1:32) NOT CHANGED
(1:40) NOT CHANGED
(1:48) NOT CHANGED
(1:56) NOT CHANGED
第二個byte0x01=00000001
一樣從右邊開始看,由於這是第二個byte,因此它代表的是從(1:64)開始
(1:64) CHANGED


(1:72) NOT CHANGED
(1:80) NOT CHANGED
(1:88) NOT CHANGED
(1:96) NOT CHANGED
(1:104) NOT CHANGED
(1:112) NOT CHANGED
(1:120) NOT CHANGED
第三個byte0x08=00001000
一樣從右邊開始看,由於這是第三個byte,因此它代表的是從(1:128)開始
(1:128) NOT CHANGED
(1:136) NOT CHANGED
(1:144) NOT CHANGED
(1:152) CHANGED
(1:160) NOT CHANGED
(1:168) NOT CHANGED
(1:176) NOT CHANGED
(1:184) NOT CHANGED
以上是逐步解析DCM bitmap的紀錄方式,以便徹底了解DCM page。我們可以將上面解析的結果,跟之前的顯示結果圖對照一下,檢查是否相同。

接下來,我們試著建立一個table,並新增一筆資料
create table test0219(c1 int identity,c2 varchar(10))
go
insert into test0219 values('test dcm')
go 10

接著我們透過dbcc ind,來檢查這個table建立在哪些個page之上
dbcc ind('TESTBAK','test0219',1)






我們可以看到test0219這個table是建立在page 77,其IAM page是在page 78
對應到extent,會是在(1:72).
原本的 (1:72) NOT CHANGED
這時候我們再用dbcc page檢查DCM頁。
dbcc page(TESTBAK,1,6,3)



















如上圖,(1:72)已經被標示成 CHANGED。至於為什麼還有其它的頁面也會被異動?那是因為我們新增的是一個table,這個資訊也會被紀錄在一些系統table之中(如sysobjectssyscolumnssysindexes等),所以才會看到有其它的頁面也跟著被標示成CHANGED

接著,我們做一次差異備份,根據之前所說,差異備份並不會去異動DCM頁。也因此後面的差異備份才會包含前面的差異備份。
backup database TESTBAK to disk='c:\test\testbak.dif' with differential
go
dbcc page(TESTBAK,1,6,3)




















經過差異備份後,DCM頁仍然保持不動。

接著我們再做一次全備份
backup database TESTBAK to disk='c:\test\testbak.bak'
go
dbcc page(TESTBAK,1,6,3)












我們可以看到,經過全備份後,DCM頁會被歸零。但如前所述,每次備份後,SQL Server會將有關該備份的訊息存儲在一些系統TABLE中。這會導致部分頁面在備份完後立即被更改,因此你永遠不會看到完全為(NOT CHANGED)的DCM

從以上的說明及實驗中,我們知道DCM page是用來紀錄從上次完整備份之後,有哪些extent被異動過。
當執行差異備份時,系統僅需檢查DCM page,就可以很快的將有異動過的extent備份出來。因此差異備份的速度快慢,與資料庫大小無關,差異備份的速度與異動量相關。

差異備份完成後,系統並不會去將DCM page歸零,因此後面的差異備份,將會涵蓋之前的差異備份。所以差異備份出來的檔案大小,會逐次的增加,直至下次完整備份為止。

SQL SERVER的三種備份方式中,全備份及差異備份,主要是針對「資料」,這兩種備份方式與交易紀錄較無關係(這兩種備份方式為了能夠recovery,它也會備走部份所需要的交易紀錄)。因此差異備份檔並不具有時間點還原的特性,當然如果有多個差異備份,你可以選擇距你想要還原的時間點最近的差異備份檔來還原。但你無法指定在某個差異備份檔案中還原到的特定時間點。

我做這個實驗的目地,主要是想更詳細的了解差異備份及其背後的原理。也在過程中,讓我學習到更深入的東西。

沒有留言:

張貼留言