當一切正常時,沒有必要特別留意什么是事務日志,它是如何工作的。你只要確保每個數據庫都有正確的備份。當出現問題時,事務日志的理解對於采取修正操作是重要的,尤其在需要緊急恢復數據庫到指定點時。這系列文章會告訴你每個DBA應該知道的具體細節。
它不會經常提起,除非你的數據庫運行在簡單(SIMPLE)恢復模式,在事務日志上定期備份非常重要的。這會控制事務日志大小,並且保證,在災難發生里,你可以恢復你的數據庫到災難發生前的某個時間點。這些日志備份要和定期的完整數據庫(數據文件)備份一起。
如果你在測試數據庫上工作,不需要恢復到先前的某個時間點,或者會樂意恢復到上次完整備份,那你就可以在簡單模式里運行數據庫。
我們來詳細討論下這些問題。
備份的重要性
考慮下,例如SQL Server數據庫“崩潰”的情況里,可能是硬件故障,“活生生”的數據文件(mdf和ndf文件),和事務日志文件都不能訪問了。
最壞的情況,其它地方不存在這些文件備份(副本),那你會遭受100%的數據丟失。為了保證你能恢復數據庫,且數據恢復到服務器崩潰前存在的某個時間點,或者恢復到數據因為其他原因丟失或損壞前,DBA需要同時為數據和日志文件做定期備份。
DBA可以進行3個主要類型的備份(但是當在簡單(SIMPLE)恢復模式時只有前2個可以應用)
- 完整數據庫備份——在數據庫里備份所有的數據。對提供的數據庫,這本質是制作MDF文件副本。
- 差異數據庫備份——自上次備份后,制作已改變的任何數據的副本。
- 事務日志備份——自上次事務日志備份,制作插入到事務日志的所有日志記錄的副本(如果在簡單(SIMPLE)恢復模式里,是數據庫檢查點)。當日志備份完成時,通常日志被截斷,這樣的話文件里的空間可以被重用,但是一些因素可以延遲這個(看第8篇——救命,我的日志滿了。)
一些初級的DBA和很多開發者,可能會被“完整”誤解,誤認為完整備份備份“一切”;數據和事務日志內容同時備份。這是不對的。本質上,完整和差異備份同時只備份數據,盡管它們也備份足夠的事務日志來啟用備份數據的恢復,當數據庫在備份時,重現任何改變。但是,實際上,完整數據庫備份不備份事務日志,也不會導致事務日志的截斷。只有事務日志備份會造成日志的截斷,因此在生產環境里,進行日志備份是唯一控制日志文件大小的正確方法。在第8篇——救命,我的日志滿了會討論一些常見但不正確的方式。
文件和文件組備份
大的數據庫有時會由多個文件組組織,是可以在各個文件組、或文件組里的文件上進行完整和差異備份,而不是備份整個數據庫。對此以后在以后的文章里不會詳談。
恢復模式
SQL Server數據庫備份和恢復操作發生在數據庫恢復模式的上下文里。恢復模式是決定你是否需要(或甚至可以)備份事務日志和操作如何記錄的數據庫屬性。對於可用恢復操作,還有頁粒度和文件恢復都有一些不同,但這個系列文章不會討論這些。
一般來說,數據庫會運行在簡單和完整恢復模式,它們之間的重用區別如下:
- 簡單(SIMPLE)——事務日志只用作數據庫恢復和回滾操作。在檢查點期間是自動截斷。它不會被備份,因此它不能用於還原數據庫到過去存在的某個時間點。
- 完整(FULL)——事務日志在檢查點期間不會自動截斷,因此可以被備份並用來還原數據到先前的某個時間點,也用作數據庫恢復和回滾。只有當日志備份發生時,日志文件會截斷。
還有第3個模式,大容量日志(BULK_LOGGED),在這個特定操作里,通常會生成很多寫入到事務日志,為了不淹沒事務日志而進行很少的記錄。
不能最小記錄的操作
可以被最小記錄的操作包括大容量導入操作(例如使用BCP或BULK INSERT),SELECT/INTO操作和特定索引操作(例如索引重建)。完整列表可以在這里找到:https://msdn.microsoft.com/zh-cn/library/ms191244.aspx
選擇正確的恢復模式
在完整恢復模式和簡單恢復模式之間選擇的最重要標准是:你願意冒丟失多少數據的風險?
在簡單恢復模式里,只有完整和差異備份。比方說你完全依賴完整備份,在每天早上2點進行完整備份,有一天服務器在早上1點的時候服務器經歷了一次致命的崩潰。在這個情況里,你只能恢復前一個早上2點的完整數據庫備份,會丟失23個小時的數據。
在完整備份之間可以進行差異備份,來減少數據丟失的風險。所有的備份都有密集的I/O流程,對於完整備份更是名副其實,其次是差異備份。他們很可能影響數據庫的性能,當用戶們正在訪問數據庫時不應該運行。實際上,如果你運行在簡單恢復模式,數據丟失的風險是幾個小時。
如果數據庫存放關鍵業務數據,你會更喜歡數據丟失是幾分鍾而不是幾個小時,那樣的話你需要運行數據庫在完整恢復模式。在這個模式里,你需要進行一次完整數據備份,然后是一系列定期的事務日志備份,再又是另一個完整備份,這樣反復進行。
在這個情況下,理論上你可以恢復最近的可靠完整備份(加上最近的差異備份,如果有的話),接下來是可用日志備份鏈,自上次完整或差異備份后。然后,在恢復過程中,在備份日志里的所有記錄的操作會前滾,將數據庫恢復到非常接近於災難時間。
日志文件備份的頻率多少會再次取決於你准備丟失的數據,加上你服務器上的工作量。在重要的金融或會計應用上,對於數據丟失的容忍幾乎為零,那樣的話你可以每15分鍾備份一次日志,甚至可以更高頻率。在剛才的備份例子里,意味着你可以恢復上午2點的完整備份,然后按順序應用每個日志文件備份,假設你有自用作數據庫恢復基礎的完整備份,有完整擴展的日志鏈(log chain)到上午12點45分,剛好在數據庫崩潰前15分鍾。事實上,崩潰后當前的日志還是可以訪問的,允許你進行尾日志備份(tail log backup),你可以最小化你的數據丟失接近為0。
日志鏈和尾日志備份……
會在第5篇——完整恢復模式里的日志管理里詳細介紹。
當然,使用完整備份會帶來更多的維護,創建和監控用來頻繁運行事務日志備份的作業,這些都要額外工作,這些備份需要I/O資源(盡管只是短時間),需要磁盤空間來存儲大數量的備份文件。對數據庫選擇合適的恢復模式前,在業務層面,這些都要慎重考慮這些。
設置和切換恢復模式
恢復模式可以使用下列簡單的命令進行設置。
1 USE master; 2 3 -- set recovery model to FULL 4 ALTER DATABASE TestDB 5 SET RECOVERY FULL; 6 7 -- set recovery model to SIMPLE 8 ALTER DATABASE TestDB 9 SET RECOVERY SIMPLE; 10 11 -- set recovery model to BULK_LOGGED 12 ALTER DATABASE TestDB 13 SET RECOVERY BULK_LOGGED;
數據庫會調整到model數據庫設置的默認恢復模式。在大多數情況下,這會意味着對於數據庫的“默認”恢復模式是完整,但SQL Server的不同版本,對於model數據庫會有不同的默認配置。
探索恢復模式
理論上,我們可以使用下列查詢找出數據庫使用的模式。
1 SELECT name , 2 recovery_model_desc 3 FROM sys.databases 4 WHERE name = 'TestDB' ; 5 GO
但是,對這個查詢要小心,因為它可能沒告訴真相。例如,如果我們創建一個新的數據庫,然后立即運行剛才的命令。它會報告這個數據庫運行在完整恢復模式下。但事實上,直到完整備份已完成前,數據庫會運行在自動-截斷模式(即簡單模式)。
我們可以在SQL Server實例上創建一個新的數據庫來驗證這個,默認的恢復模式是完整。我們創建有一些測試數據的表,然后檢查下恢復模式。
1 /* STEP 1: CREATE THE DATABASE*/ 2 USE master ; 3 4 IF EXISTS ( SELECT name 5 FROM sys.databases 6 WHERE name = 'TestDB' ) 7 DROP DATABASE TestDB ; 8 9 CREATE DATABASE TestDB ON 10 ( 11 NAME = TestDB_dat, 12 FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\TestDB.mdf' 13 ) LOG ON 14 ( 15 NAME = TestDB_log, 16 FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Data\TestDB.ldf' 17 ) ; 18 19 /*STEP 2: INSERT A MILLION ROWS INTO A TABLE*/ 20 USE TestDB 21 GO 22 IF OBJECT_ID('dbo.LogTest', 'U') IS NOT NULL 23 DROP TABLE dbo.LogTest ; 24 SELECT TOP 1000000 25 SomeID = IDENTITY( INT,1,1 ), 26 SomeInt = ABS(CHECKSUM(NEWID())) % 50000 + 1 , 27 SomeLetters2 = CHAR(ABS(CHECKSUM(NEWID())) % 26 + 65) 28 + CHAR(ABS(CHECKSUM(NEWID())) % 26 + 65) , 29 SomeMoney = CAST(ABS(CHECKSUM(NEWID())) % 30 10000 / 100.0 AS MONEY) , 31 SomeDate = CAST(RAND(CHECKSUM(NEWID())) 32 * 3653.0 + 36524.0 AS DATETIME) , 33 SomeHex12 = RIGHT(NEWID(), 12) 34 INTO dbo.LogTest 35 FROM sys.all_columns ac1 36 CROSS JOIN sys.all_columns ac2 ; 37 38 SELECT name , 39 recovery_model_desc 40 FROM sys.databases 41 WHERE name = 'TestDB' ; 42 GO
這表示我們運行在完整恢復模式,但現在我們檢查下日式空間使用
1 DBCC SQLPERF(LOGSPACE) ; 2 -- DBCC SQLPERF reports a 110 MB log file about 90% full3
強制一個檢查點(CHECKPOINT),再次檢查日志使用率。
1 CHECKPOINT 2 GO 3 4 DBCC SQLPERF(LOGSPACE) ; 5 -- DBCC SQLPERF reports a 100 MB log file about 60% full
注意日志文件近乎一樣的大小,但是現在只有61.9%滿;日志已被截斷,空間可以被重用。雖然數據庫被指定為完整恢復模式,實際上這個不應該操作直到第一次完整備份發生后。很有意思,這表示我們可以通過強制檢查點(CHECKPOINT),而不是運行TestDB數據庫的完整備份。完整備份操作操作觸發了檢查點(CHECKPOINT),且日志被截斷。
為了確定數據庫運行在哪個模式里,執行下列查詢:
1 SELECT db_name(database_id) AS 'DatabaseName' , 2 last_log_backup_lsn 3 FROM master.sys.database_recovery_status 4 WHERE database_id = db_id('TestDB') ; 5 GO
如果NULL值出現在last_log_backup_lsn列里,那么數據庫實際上運行在自動截斷模式,因此當數據庫檢查點發生時會截斷。已經進行了完整數據庫備份,你會發現那列會填上備份操作記錄的日志記錄的LSN,在這時,數據庫菜真正運行在完整恢復模式。從這一刻開始,完整數據庫備份不會在事務日志上影響;唯一截斷日志的方法是備份日志。
切換模式
如果你曾從完整或大容量日志模式切換到簡單模式,這會中斷日志鏈,你只能恢復數據庫到在你切換前,上一次日志備份的時間點。因此,不建議在切換前馬上進行日志備份。如果你馬上從簡單模式切換到完整或大容量日志模式,記住數據庫實際上會繼續運行在自動截斷模式(剛才顯示的NULL值),直到你進行了另一個完整備份。
如果你從完整切換到大容量日志,那這不會中斷日志鏈。但是在大容量模式里發生的任何大容量操作不會在事務日志里完整記錄,因此不能在操作上控制,同樣的方法里完整記錄可以。這表示恢復數據到包含大容量操作事務日志里的時間點是不可能的。你只能恢復到日志文件尾。為了“重新啟用”到時間點的恢復,在大容量操作完成后切換回完整模式,並立即進行一次日志備份。
備份的自動化和驗證
即席數據庫和事務日志備份可以通過SSMS里簡單的T-SQL腳本進行。但是對於生產系統,DBA需要這些備份的自動化方法,還有驗證備份的有效,可以用於還原你的數據。
這個話題的詳細講解已經不是這個系列文章的范圍,但會在下面列出一些可用選項。由於SSMMS維護計划的一些問題,大多數DB會選擇自己寫腳本,然后用作業自動運行它們。
- SSMS維護計划向導和設計器——SSMS內建的2個工具,允許你配置和計划一系列的核心數據庫維護任務,包括完整數據庫備份和事務日志備份。DBA也可以運行DBCC完整性檢查,安排作業來刪除老的備份文件等等。這些工具的精彩描述,還有它們的限制,可以在Brad McGhee的《Brad的SQL Server 維護計划指導手冊》里找到。
- T-SQL腳本——你可以寫定制的T-SQL腳本來自動化你的備份任務。一個廣為流傳的維護腳本是Ola Hallengren提供的。它的腳本創建了各種存儲過程,每個進行一個特定的數據庫維護任務,包括備份,自動地使用SQL代理作業。Richard Waymire的SQL Server代理步步高是關於這個話題的良好信息來源。
- Powershell/SMO腳本——比T-SQL腳本更強大,更通用,但對大多數DBA來說學習曲度更陡峭。Powershell可以用作腳本,自動化幾乎任何的維護任務。例子可以看下:https://www.simple-talk.com/author/allen-white/
- 第3方備份工具——很多現存的第三方工具可以自動化備份,也可以驗證和監控它們。大多數提供備份壓縮和加密等功能讓備份管理更加簡單。例子包括Red Gate的SQL Backup,Quest的LiteSpeed等等。