本篇文章是系列文章中的第四篇,也是最后一篇,本篇文章需要前三篇的文章知識作為基礎,前三篇的文章地址如下:
淺談SQL Server中的事務日志(一)----事務日志的物理和邏輯構架
淺談SQL Server中的事務日志(二)----事務日志在修改數據時的角色
淺談SQL Server中的事務日志(三)----在簡單恢復模式下日志的角色
簡介
生產環境下的數據是如果可以寫在資產負債表上的話,我想這個資產所占的數額一定不會小。而墨菲定律(事情如果有變壞的可能,無論這種可能性有多小,它總會發生)仿佛是給DBA量身定做的。在上篇文章介紹的簡單恢復模式下,從最近一次備份到當前的數據都會存在丟失的風險。而完整備份模式使得數據丟失的風險大大減少。本文主要介紹在完整備份模式下概念原理和日志所處的角色。
完整(Full)恢復模式
完整恢復模式通過將對數據庫的任何修改記錄到日志來給予數據最大程度的保護。在完整恢復模式下,日志的作用不僅僅是保證了數據庫事務的ACID。並且還可以使數據恢復到在日志范圍內的任何時間點。
在上一篇文章中說過,在簡單恢復模式下,日志幾乎是不用進行管理的。每一次CheckPoint都有可能截斷日志,從而來回收不活動的VLF以便重復利用空間。因此在簡單恢復模式下,日志的空間使用幾乎可以不去考慮。與之相反,在完整恢復模式下,日志作為恢復數據的重要組成部分,日志的管理和對日志空間使用的管理則需要重視。
在完整恢復模式下,CheckPoint不會截斷日志。只有對日志的備份才會將MinLSN向后推並截斷日志。因此在一個業務量稍大的系統中,日志的增長速度將會變得很快。
因此日志備份的目的分為以下兩個:
- 減少活動日志的大小
- 減少日志損壞的風險
通過從MSDN中摘自的下圖可以看到:
在DB_1處做了完整備份,並且接下來兩次分別做了兩次日志備份(Log_1和Log_2),在Log_2備份完不久服務器由於數據所在磁盤損壞。這時如果日志文件完好,則可以通過備份尾部日志(Tail of log)后,從DB_1開始恢復,依次恢復Log_1,Log_2,尾部日志來將數據庫恢復到災難發生時的時間點。理論上可以使數據的損失為0。
從日志恢復數據的原理是Redo,也就是將日志中記載的事務再重做一遍。這個開銷和從完整或差異備份中恢復相比,要大很多。因此盡可能的減少利用日志的恢復量。而使用完整或者差異備份來恢復更多的數據。
大容量日志(Bulk-logged)恢復模式
大容量恢復模式在很多地方和完整恢復模式相同。但由於在完整恢復模式下,對數據庫的每一項操作都會記錄在日志中。而對於某些大量數據的導入導出操作,無疑會在日志中留下大量記錄。很多情況下,我們並不需要將這些信息記錄在日志中。
而大容量日志恢復模式作為完整恢復模式的備選方案。微軟推薦的最佳實踐是在進行大量數據操作時(比如索引的創建和rebuilt,select into操作等),暫時由完整恢復模式切換到大容量恢復模式來節省日志。這個轉換並不會破壞日志鏈。
本文不會深入探討這個模式,僅僅是對這個概念做簡單解釋。假設我要插入一批數據,則完整恢復模式和大容量日志恢復模式在日志中所記錄的信息如下:
由此可以看出,在日志中,大容量恢復模式將這類操作變為一個原子。
日志鏈(Log Chain)
連續的日志備份被稱之為日志鏈。表示日志是連續的.這個概念可以用下圖表示:
假設上面兩個日志備份可以簡單抽象成如上2個備份,則日志備份1的末尾LSN必須小於等於日志備份二的第一個LSN(通常情況下是第一個末尾LSN等於第二個日志備份的第一個LSN,但由於存在“只備份日志”選項只備份日志,並不截斷日志,所以有可能重疊)。則這兩個備份的日志鏈是連續的。
下圖是一個生產環境下,在SSMS中查看日志鏈連續的例子:
可以看出,第一次完整備份后,備份多次事務日志,每一個事務日志的開始LSN都等於上一個事務日志的結束LSN。因此可以從第一次完整備份開始,恢復到最后一個日志備份期間的任何時間點。
完整的日志鏈以第一次完整備份或由簡單恢復模式轉為完整或大容量日志模式開始,到當前的時間點結束。
而從日志恢復數據要求從最近一次完整或差異備份到所恢復的時間點之間的日志鏈是連續的。
恢復次序
從備份恢復數據需要經歷如下幾步驟:
1.復制數據階段:從完整備份和差異備份中將數據,索引頁和日志復制到被恢復數據庫文件。
2.Redo(roll forward)階段:將記錄在日志中的事務應用到從備份中復制過來的數據。使數據Roll Forward到指定的時間點.這個階段完成后,數據庫還處於不可使用階段:
上面兩部就是Restore
3.Undo(Roll Back)階段:這也是傳說中的Recovery,將任何未提交的事務回滾。這個階段過后,數據庫處於可用狀態。任何后續備份將不能接着應用到當前數據庫。
這個概念比如:
在連續兩個日志鏈的日志備份,在第一個事務日志備份中定義的事務,在第二個事務日志備份中Commit.如果在第一個事務日志還原后使用了Recovery選項.也就是經歷了Undo階段。則事務1在Undo階段會被回滾:
可見,日志備份1中的T1被回滾,在日志備份2中的Commit也就毫無意義。這也就是為什么經歷過Undo階段后不允許再恢復后續備份。因此,微軟推薦的最佳實踐是使用NoRecovery選項不進行Undo階段。而在所有備份恢復后單獨進行Undo階段,這個操作可以通過還原日志尾部時,指定Recovery選項進行。
總結
本文簡單介紹了在完整恢復模式下,日志的作用以及對數據恢復的一些概念。理解完整恢復模式的概念對於減少數據丟失的風險是無可替代的。