導言
完整備份不能截斷事務日志,這是所有SQL Server DBA的一個常識,
為此,當數據庫處于完整恢復模式時(非特別說明,下文所提到都是完整恢復模式下的數據庫),DBA們必須頻繁地使用事務日志備份的方式來防止日志文件變得過大。
這幾乎成為了DBA們的一個定理,但,作為一個DBA,你證明過這個定理嗎?你知道為什么完整備份不能截斷事務日志嗎?
一個錯誤的”常識“
將一個完整備份還原到新數據庫時,新數據庫無論是mdf還是ldf,其大小都跟原始數據庫一模一樣,
以至于我們認為完整備份包括了mdf中所有數據和ldf中的所有事務日志。這幾乎成為了一些DBA的”常識“。
正是如此,我們有”理由“認為:數據庫在完整備份后,ldf中的事務日志應該被截斷,沒必要再保存一個副本。
讓“常識”站不住腳
按照這個”常識“,既然完整備份中包含了原始數據庫中所有的事務日志,那通過完整備份還原得到的新數據庫應該也含有同樣的事務日志。下面我們通過一個小實驗來驗證實際情況是否是這樣。
驗證思路:
CREATE DATABASE test;
USE Test;
CREATE TABLE t1(col1 INT,col2 VARCHAR(25));
ALTER DATABASE Test SET RECOVERY FULL;
--在表中插入5條數據
INSERT INTO t1 VALUES(1,'chen1');
INSERT INTO t1 VALUES(2,'chen2');
INSERT INTO t1 VALUES(3,'chen3');
INSERT INTO t1 VALUES(4,'chen4');
INSERT INTO t1 VALUES(5,'chen5');
BACKUP DATABASE Test TO DISK='d:\temp\oldtest.bak'
--完整備份數據庫
--還原到新數據庫RESTORE DATABASE test_new FROM DISK='d:\temp\oldtest.bak' WITH MOVE 'test' TO 'd:\temp\test.mdf', MOVE 'test_log' TO 'd:\temp\test_log.ldf' --對比新老數據庫LDF中的事務日志大小 DBCC SQLPERF(LOGSPACE)
--結果:LDF文件大小相同
--對比新老數據庫LDF中的事務日志內容(通過ApexSQL Log軟件分析新老數據庫的LDF文件)
--結果:原數據庫和新數據庫的事務日志不相同

結論1:
通過完整備份文件還原得到的數據庫,盡管其LDF的大小與原數據庫相同,但兩者所包含的事務日志并不完全相同,如上例所述,原數據庫test包含5條insert的事務日志,而新數據庫test_new沒有這些事務日志。如果完整備份截斷了事務日志,則無論是原數據庫的LDF文件還是完整備份文件,都將不包含事務日志,這無異于將數據庫置于簡單恢復模式下,顯然不符合我們將數據庫設置成完整恢復模式的初衷。
完整備份的那些事
通過上述實例我們已經有了足夠的理由推翻那個錯誤的“常識”,但,這個例子似乎并不完美,因為它又將我們導向了另一個錯誤的極端——完整備份不包括任何事務日志。
真是這樣的嗎?
本質是是現象的根源,只有真正了解了數據庫完整備份期間發生的那些事,我們才能揭開層層迷霧。
歸納起來,數據庫的完整備份主要包括如下幾個步驟:
-
執行Checkpoint,并標記此時數據庫中事務日志的LSN
-
開始讀取、拷貝data files中的數據
-
結束data files的讀取和拷貝,并記錄此時最后一個活動日志的起始LSN
-
讀取并拷貝必需的日志文件
摘自:http://technet.microsoft.com/en-us/magazine/2009.07.sqlbackup.aspx#id0980008
備注:讀者在查看上述日志時,請先開啟3004、3605、3502這三個跟蹤標記。
至此,我們已經明白了,在完整備份文件里,它雖然沒有包含所有的事務日志,但在完整備份期間,拷貝日志的動作一直存在,按照SQL Server的說法,完整備份選擇性的保存了數據庫必需的事務日志。
為什么要選擇性的保存這些必需事務日志呢?什么是“必需的事務日志”?而我的樣例中新數據庫為何沒有任何事務日志?
在回答這些問題前,我們先看一下MSDN對完整備份文件的一個描述:
也就是說,完整備份文件能夠呈現數據庫在備份完成時間點的所有數據,那么,這些足夠多的事務日志的目的肯定是為了將數據庫還原到備份完成時的時間點。
有了這個概念,我們來看一個完整備份的場景,下圖綠色的數字代表完整備份的每個步驟:
- 執行事務A
- 執行完整備份和checkpoint,開始讀取和拷貝數據文件
- 備份進程讀取數據頁X
- 執行事務B,改變數據頁X的數據
- 結束事務B
- 結束對數據文件的讀取和拷貝
數據庫的完整備份從時間點2持續到時間點7。
對于頁面 X,在時間點3做了備份后,在時間點5被事務B做了修改,因此,此時備份文件中頁面X的數據已經過期了、不準確,而備份進程不會回過頭來重新讀取頁面X。因為“完整備份文件必須呈現數據庫在備份完成時間點的所有數據”,所以,數據庫必須備份事務B的日志,以便在數據庫通過重做此日志還原到時間點7的狀態。
對于事務A,其執行的時間早于備份的開始時間,且在數據文件備份期間一直沒有結束,是這次完整備份的活動事務。
盡管事務A沒有提交,但時間點2的checkpoint已將事務A所做的修改寫入到數據文件中,如果完整備份文件沒有包含事務A的日志,則這些未提交的修改將無法得到回滾,導致數據不一致的情況發生。
綜上所述:
結論2
如果在完整備份前不存在活動事務,則必需的事務日志范圍:從備份開始時的LSN到備份結束時的LSN;
如果在完整備份前存在活動事務,則必需的事務日志范圍:從最早活動事務開始的LSN到備份結束時的LSN;
在我之前的樣例中,因為5條insert語句在數據庫備份前已經執行完成并提交了,所以備份文件不會保存這些日志,因而在還原得到的新數據庫中看不到這些日志。
至此,我們已經完成了這個定理的證明過程,感謝各位的耐心品讀,歡迎大家批評指教。
文章列表