SQL Server事務日誌管理的級別,第5級:在徹底恢復模式下管理日誌

原文連接:http://www.sqlservercentral.com/articles/Stairway+Series/73785/web

做者:Tony Davis2012/01/27 sql

關於該系列數據庫

本文是階梯系列的一部分:SQL Server中事務日誌管理的階梯服務器

只要操做順利進行時,不須要特別注意事務日誌是作什麼的或者它是如何工做的。你只須要相信每一個數據庫都有正確的備份機制。當出現問題時,瞭解事務日誌工做並採起糾正措施就很是重要了,特別是須要在某些時間點對數據庫進行恢復操做。Tony Davis給出了每一個DBA應該知道的糾正層級的細節。工具

在此級別中,咱們將回顧在徹底恢復模式工做時進行日誌備份的緣由和方法,以及如何使用這些日誌備份文件與徹底數據庫備份實現數據庫還原。徹底恢復模式支持將數據庫恢復到可用日誌備份中的任什麼時候間點,假設能夠在失敗發生以前,也就是執行最後一次提交事務的時間以前執行尾日誌備份。sqlserver

要記錄什麼?測試

在徹底恢復模式下,全部操做都將被徹底記錄。對於對行進行操做的插入、更新和刪除操做,這意味着對於修改的每一行,都會有一個日誌記錄日誌記錄執行該語句的事務的ID描述該事務開始和結束時,哪些頁面被更改,哪些數據被更改,等等。ui

在徹底恢復模式下,最低限度執行SELECT INTOBULK INSERTCREATE INDEX的操做仍然是徹底記錄,但操做方式略有不一樣。執行操做後受影響的行不會被單獨記錄;只有在執行的數據庫頁面在被填滿時纔會被記錄的日誌中。這就減小了這些操做的日誌記錄,同時也能確保執行回滾、重作和時間點恢復所需的全部相同信息都存在。Kalen Delaney發表了一些關於日誌記錄的調查,用於在批量日誌和bulk_logging恢復模式下的SELECT into操做 (http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/15/what-gets-logged-for-select-into.aspx) 和索引重建操做(http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/08/what-gets-logged-for-index-rebuilds.aspx) 。在bulk_logging模式下工做時,在記錄最小日誌操做上二者會產生差別,這將在第6級—在批量日誌恢復模式下管理日誌中進行更詳細的討論。spa

爲何備份事務日誌?設計

在徹底恢復模式下,只有日誌備份可能致使截斷日誌。 事務日誌將保存上次備份事務日誌以來執行的完整事務記錄。 因爲全部操做都已徹底記錄,所以在繁忙的系統中,日誌文件擴展的很是快。

所以,在徹底恢復模式下工做時,除了徹底備份和(可選)差別備份以外,還必須執行常規事務日誌備份。 許多新手或兼職DBA在數據庫上執行徹底備份,不執行事務日誌備份。此時,事務日誌不會被截斷,它會一直增長,直到它所在的驅動器磁盤空間用完,這時SQL Server中止纔會工做。

一旦開始進行日誌備份,日誌就會當即截斷,例如執行數據備份或恢復操做,若是上次備份已經產生了檢查點,那就沒有其餘因素會致使延遲截斷可能延遲截斷的時候,可恢復VLF的因素的完整列表保留大量日誌活動的因素,不然將不須要,例如非法的、長時間運行的未提交事務或數據庫鏡像或複製進程,請參見:http://msdn.microsoft.com/en-gb/library/ms345414.aspx.

      COPY_ONLY備份事務日誌

      COPY_ONLY事務日誌備份不會截斷事務日誌。 COPY_ONLY日誌備份獨立存在於正常日誌備份方案中; 它不會破壞日誌備份鏈。

簡而言之,事務日誌備份執行容許恢復恢復到上一個時間點以及控制事務日誌的大小的雙重目的。與事務日誌相關的問題最多見的緣由多是在徹底恢復模式下工做,沒有進行日誌備份,或者沒有頻繁地進行日誌備份以控制事務日誌文件的大小。

若是你不肯定是否對給定的數據庫進行了事務日誌備份,那麼你可使用相似於列表5.1所示的查詢,在MSDB數據庫中簡單地查詢 backupset表。

列表5.1:是否進行日誌備份?

type列中,D表示數據庫備份,L表示日誌備份,I表示差別備份。

請注意,因爲能夠在不影響備份和還原行爲的狀況下操做backupset表中的數據,所以你想要經過查詢sys.database_recovery_status查看last_log_backup_lsn(參見清單3.5)或sys.databases表查看log_reuse_wait_desc的值(若是須要備份,將返回LOG_BACKUP)。

如何備份事務日誌?

正如前面所討論的,若是沒有進行至少一次完整備份,沒法執行事務日誌備份。事實上,若是的數據庫處於徹底恢復模式但從未進行過備份,它不會在徹底恢復模式下工做。在執行第一次完整備份以前,數據庫將處於自動截斷模式。

全部數據庫備份包括完整備份、日誌備份或其餘備份都使用BACKUP命令執行。該命令許多選項,這些選項在這裏有記錄:http://msdn.microsoft.com/en-us/library/ms186865.aspx。然而,在最基本的狀況下常使用,執行磁盤徹底備份的命令以下:

BACKUP DATABASE DatabaseNameTO DISK ='FileLocation\DatabaseName.bak';

若是這是要執行的第一個備份,則系統將在指定的目錄中建立DatabaseName.bak文件。若是此類文件已存在,則默認行爲是將後續備份附加到該文件。要覆蓋此行爲,並規定覆蓋現有任何文件,咱們可使用INIT選項,以下所示:

BACKUP DATABASE DatabaseNameTO DISK ='FileLocation \ DatabaseName.bak'WITH INIT;

可是,最多見的是,每一個後續備份都有一個惟一的名稱; 關於這一點,請下一節恢復到故障點。

在每次按期(例如天天)完整備份以後,將會有頻繁(例如每小時)的日誌備份,其基本命令很是類似:

BACKUP LOG DatabaseNameTO DISK ='FileLocation \ DatabaseName_Log.bak';

存儲日誌備份?

顯然,備份的數據和日誌文件不該該存儲在承載活動文件的同一驅動器上。若是該驅動器發生硬件故障,那麼的全部副本將與活動文件一塊兒丟失,備份將是徒勞的。文件應該備份到單獨的設備,或者備份到本地鏡像驅動器。

日誌備份頻率?

如前面的級別所述,可能每15分鐘或甚至更頻繁地進行日誌備份。 在這種狀況下,爲了不須要還原大量的事務日誌文件,能夠選擇採用一種由徹底備份組成的備份方案,其中穿插了差別備份和事務日誌備份。

實際上,備份方案一般理想和實際之間的綜合,是對數據丟失的真實風險以及它將給公司帶來成本的評估,下降這種風險所涉及的成本之間的折衷。許多很是重要的業務應用程序使用稍微簡單但仍然嚴格的備份方案,可能涉及按期夜間完整備份甚至每小時事務日誌備份。

日誌備份的頻率也能夠由數據庫所涉及的事務數量決定。對於很是繁忙的數據庫,可能須要常常備份以便控制日誌的大小。

沒有簡單的方法來計算日誌備份的頻率。 大多數DBA會對日誌備份的頻率進行最佳估計,而後觀察文件的增長的特性,而後根據須要調整備份方案,以防止它們變得過大。

日誌鏈和如何打破日誌鏈?

如上所述,若是沒有首先進行至少一次完整備份,則沒法執行事務日誌備份。爲了數據庫恢復到某個時間點,或者恢復到在特定日誌備份結束時或者在特定日誌備份中的某個時間點,必須完整的不間斷的日誌記錄鏈,從第一第二天志備份開始在完整(或差別備份)以後,直到故障點。這稱爲日誌鏈。

有許多方法能夠破壞日誌鏈,將數據庫恢復到在事件發生以前進行日誌備份,就意味着會破壞鏈。簡而言之,若是關心恢復數據的能力,那麼打破這個鏈條並非一個好主意。打破鎖鏈最多見的兩種方式包括:事務日誌備份文件的丟失或損壞——將只能恢復到上一次良好的日誌備份。日誌鏈將在下一個良好的徹底備份或差別備份時再次啓動。

切換到簡單恢復模式——若是從徹底恢復模式切換到簡單恢復模式,這將打破日誌鏈,由於啓動檢查點,而且當即截斷事務日誌。當返回到徹底恢復模式時,須要另外一個完整備份來從新啓動日誌鏈。事實上,在進行完整備份以前,數據庫將保持自動截斷模式,沒法備份日誌文件。

SQL Server 2008以前,有一些命令,即BACKUP LOG WITH NO_LOGBACKUP LOG WITH TRUNCATE_ONLY(它們在功能上等效),當命令發出時,執行日誌文件會強制被截斷,從而破壞日誌鏈。也就是說不能在任何版本的SQL Server中發出這些命令,可是在這裏提到它們,由於在處理「失控的日誌文件」時,若是不理解這些命令對恢復數據庫的能力的影響,仍然會被粗心的人使用。恢復他們的數據庫有關更多詳細信息,請參閱第8- 幫助,個人日誌已滿。

尾部日誌備份?

只要有一個最近的完整備份和一個完整的日誌鏈,您就能夠將數據庫恢復到它在任何失敗以前的最後日誌備份結束時的狀態。可是,假設每小時進行事務日誌備份,而後在下午1:45發生故障。你可能會損失45分鐘的數據;事實上,若是這些錯誤不可逆的,那麼實時事務日誌是不可檢索的,那麼這就是丟失的數據量。

可是,有時即便數據文件不可用,實時事務日誌仍然可用,特別是事務日誌包含在單獨的專用驅動器上。若是是這種狀況,則應備份實時事務日誌,即執行自上第二天志備份以來生成的日誌記錄的最終備份。這將捕獲實時日誌文件中的剩餘日誌記錄,直至故障點。這稱爲尾部日誌備份,是在開始還原和恢復操做以前應執行的最後一個操做。

尾部日誌備份和最低日誌記錄的操做

若是因爲數據庫故障致使數據文件不可用,而且日誌的尾部包含最少日誌記錄的操做,那麼就不能執行尾日誌備份,由於這須要訪問數據文件中已更改的數據區段。這將在第6以批量記錄模式管理事務日誌中進行更詳細的介紹。

若是要還原的數據庫處於聯機狀態,則會按以下方式備份日誌尾部

BACKUP LOG DatabaseNameTO DISK ='FileLocation \ DatabaseName_Log.bak'WITH NORECOVERY

NORECOVERY選項將數據庫置於還原狀態,並假定您要執行的下一個操做是恢復。若是數據庫處於脫機狀態且沒法啓動,仍應嘗試按照上述描述備份日誌尾部(儘管可省略NORECOVERY選項,由於不會進行任何事務處理)。

若是肯定日誌文件已損壞,則這裏建議你使用最後的方法,嘗試使用如下命令執行尾部日誌備份:

BACKUP LOG DatabaseNameTO DISK ='FileLocation \ DatabaseName_Log.bak'WITH CONTINUE_AFTER_ERROR

若是主數據庫和數據文件已損壞,但日誌可用,Microsoft建議重建master數據庫,而後備份上一個活動日誌。可是,這些主題超出了本級的範圍,我建議參閱文檔瞭解更多細節http://msdn.microsoft.com/en-us/library/ms190952.aspx

執行恢復和恢復?

在執行了尾日誌備份以後,若是可能,下一步是恢復最後一個完整備份(若是合適的話,接下來是差別備份),而後恢復完整的日誌備份文件序列,包括尾日誌備份。這個還原操做序列的基本語法以下:

RESTORE {DATABASE | LOG} DatabaseNameFROM DISK ='FileLocation\FileName.bak'WITH NORECOVERY;

若是在恢復時省略了WITH NORECOVERY選項,那麼默認狀況下,恢復命令將繼續恢復。換句話說,SQL Server將嘗試協調數據和日誌文件,前滾已完成的事務,而後根據須要回滾未完成的事務。經過WITH NORECOVERY,指示SQL Server輸入恢復序列,使得在執行任何回滾以前前滾更多操做。在還原序列中還原最後一個備份後,能夠按以下方式恢復數據庫:

RESTORE DATABASE DatabaseName WITH RECOVERY

常見的要求是將數據庫還原到其餘位置,在這種狀況下,只需將文件做爲還原過程的一部分進行移動,以下所述:http//msdn.microsoft.com/en-us/library/ms190255.aspx

數據庫故障後的恢復?

下面的示例描述如何在數據庫數據文件再也不可訪問的狀況下恢復數據庫。

徹底恢復到失敗點?

假設實時事務日誌能夠在多是由硬件故障引發的數據庫故障以後到達,那麼在理論上,應該能夠經過如下步驟恢復和恢復數據庫,直到出現故障爲止:

1.恢復最近的完整備份(加上差別,若是適用)

2.依次恢復在徹底(或差別)備份以後並在故障發生以前完成的每一個事務日誌備份

3.還原尾日誌備份

4.恢復數據庫

聯機叢書中的許多示例演示了從備份集」(也就是存儲全部備份的單個設備」)恢復和恢復。在實際操做中,這意味着,當備份到磁盤時,備份設備是位於磁盤的某個地方單個的.bak文件

例如,列表5.2所示的簡單示例是使用一個完整備份和一個事務日誌備份組成的備份集,示例展現瞭如何執行完整還原。爲了運行這段代碼,你首先須要從新建立testdb數據庫,而後插入一些數據行(爲方便起見,執行此操做的腳本CreateAndPopulateTestDB.sql包含在此級別的代碼下載中)還須要在數據庫服務器的本地C:驅動器上建立一個備份目錄,根據須要修改文件路徑。

聯機叢書中的許多示例演示了從備份集」(也就是存儲全部備份的單個設備」)恢復和恢復。在實際操做中,這意味着,當備份到磁盤時,備份設備是位於磁盤的某個地方單個的.bak文件

例如,列表5.2所示的簡單示例是使用一個完整備份和一個事務日誌備份組成的備份集,示例展現瞭如何執行完整還原。爲了運行這段代碼,你首先須要從新建立testdb數據庫,而後插入一些數據行(爲方便起見,執行此操做的腳本CreateAndPopulateTestDB.sql包含在此級別的代碼下載中)還須要在數據庫服務器的本地C:驅動器上建立一個備份目錄,根據須要修改文件路徑。

列表5.2:備份從備份集中恢復;不推薦

然而,使用備份集彷佛是數據庫備份到磁帶時代的遺留問題。備份到磁盤時,使用這種方案是一個很差的方式,由於,這時備份文件將迅速擴展到很是大。

實際上,更常見的狀況是,每一個完整的備份和事務日誌備份文件都將單獨命名,而且可能會標記備份的時間和日期。例如,大多數第三方備份工具、流行的社區生成腳本,以及SSMS中的維護計劃嚮導/設計器,都將建立單獨的日期文件,例如AdventureWorks_FULL_20080904_000001.bak

所以,更常見的備份和還原方案將使用惟一命名的備份,如列表5.3所示。

列表5.3:備份和恢復惟一命名的備份文件

恢復到上次良好日誌備份時間點

不幸的是,有時可能沒法執行徹底恢復;例如,若是因爲活動事務日誌操做失敗而不可用。這種狀況下,咱們只恢復到最近一第二天志備份的末尾。因此須要爲包含事務日誌的驅動器出現故障這種可能的發生作好準備,這決定了日誌備份的頻率。若是每15分鐘備份一次,那麼面臨丟失15分鐘數據的風險。

假設咱們已經執行了列表5.4中所示的備份序列。爲了演示這個示例,咱們覆蓋了之前的備份文件,備份序列顯然比實際要短得多。

列表5.4:一系列簡短的日誌備份

若是凌晨2:30不久後發生災難性故障,咱們可能須要將數據庫恢復到日誌備份2結束時的狀態,即凌晨2:30

這個例子中的恢復序列與咱們以前在列表5.3中看到的很是類似,可是因爲不可能進行尾部備份,並且咱們只能恢復到某個點,所以須要使用STOPAT選項,如列表5.5所示。

列表5.5:使用STOPAT恢復到某個時間點

因爲咱們在以後指定了一個STOPAT時間,所以此代碼將前滾全部已完成的事務,直到第二個事務日誌結束。

或者,也能夠指定一個STOPAT時間,該時間位於特定日誌文件中記錄的事務的時間範圍內。在這種狀況下,數據庫將恢復到指定時間時最後提交的事務。當你知道要恢復到什麼時間段,但不知道日誌備份包含的具體時間時,這種方法很是有用。

也能夠恢復到特定的標記事務。例如,當你須要將某個應用程序訪問的多個數據庫恢復到邏輯一致的點時,這是很是有用的。本文再也不進一步討論這個主題,但你能夠在網上找到更多相關書籍(http://msdn.microsoft.com/en-us/library/ms187014.aspx)Mladen Prajdic在這裏提供了一個很好的例子:http://weblogs.sqlteam.com/mladenp/archive/2010/10/20/sql-server-transaction-marks-restoring-multi -database -to-a-common.aspx

很差的交易」以後恢復

除了全部數據庫故障的上下文以外,其餘還須要還原數據庫備份和事務日誌,以便在錯誤的數據修改以前將數據庫返回到特定時間點,例如刪除或截斷表。

你對這種狀況的反應將取決於問題的性質。若是可能,你能夠斷開全部用戶與數據庫的鏈接(在通知他們以後),並評估剛剛發生的事情的影響。在某些狀況下,你可能須要估計問題發生的時間,而後使用時間恢復點對數據庫和日誌進行徹底恢復。

恢復完成後,您必須通知用戶一些事務可能已經丟失,並請求原諒。

固然,一般你沒法以這種方式中斷正常的業務操做,以修復意外的數據丟失。因爲活動數據庫仍在運行和被訪問,你能夠嘗試在備用模式下恢復數據庫的備份。這容許恢復進一步的日誌備份,但與使用NORECOVERY時不一樣,數據庫仍然是可讀的。恢復方案多是這樣的:

  1. 在備用模式下,在活動數據庫旁邊恢復數據庫的備份
  2. 將日誌前滾到錯誤事務發生以前的位置,防止數據丟失。
  3. 將丟失的數據複製到活動數據庫中,並刪除恢復的副本。

固然,這個過程不必定是直接的,並且可能至關耗時。除非你購買了專門的日誌讀取工具,能夠直接查詢日誌備份,不然前滾日誌可能意味着一系列步驟都消失,包括恢復日誌、檢查數據、進一步恢復等等,除非你確切地知道錯誤事務發生在哪裏。步驟3也可能很困難,由於你將向活動系統中引入不必定與數據庫當前狀態一致的數據,所以可能存在引用完整性問題。

讓咱們看一下實現上面步驟1和2的示例。首先,讓咱們從頭開始運行CreateAndPopulateTestDB。從新建立TestDB數據庫的sql腳本,並將10行測試數據插入新的LogTest表中。在列表5.6中,咱們只是作了一個完整的數據庫備份(覆蓋之前的任何備份文件)。若是尚未建立「備份」目錄,則須要建立「備份」目錄,或者根據須要調整路徑。

列表5.6TestDB的徹底備份

而後,咱們將一行新數據插入LogTest表。

列表5.7:在TestDB中插入第11

因此如今咱們在LogTest表中有一個包含11行的實時TestDB數據庫,以及一個包含10行的備份版本。如今讓咱們在日誌備份中捕獲其餘修改,如列表5.8所示。

列表5.8:TestDB的日誌備份

如今,咱們要模擬一個錯誤的「很差的事務」,只需刪除LogTest表,而後執行最後的日誌備份。

列表5.9:災難!

爲了在不中斷正常業務操做的狀況下檢索丟失的數據,咱們將以備用模式恢復TestDB數據庫的副本。備用數據庫的數據和日誌文件(稱爲ANewTestDB)將移至「備用」目錄(你須要事先建立此目錄)。

列表5.10:在待機模式下恢復TestDB的一個副本

如今咱們有了一個新的數據庫,名爲ANewTestDB,它處於「備用/只讀」模式,如圖5.1所示。

5.1:備用數據庫

ANewTestDB數據庫中的LogTest表的查詢10行。可是,咱們但願將表恢復到它被錯誤刪除以前的狀態。所以,下一步是將日誌備份還原到備用數據庫。

列表5.11:在備用模式下,將日誌備份恢復到ANewTestDB數據庫

如今,已經對ANewTestDB的查詢11行,咱們能夠準備將這些數據複製回活動數據庫。若是咱們進一步恢復第二第二天志備份,那麼進程就會太快,這時備用數據庫中的表會丟失。

另外一種備用恢復方法是考慮使用第三方工具,好比Red Gate的SQL Virtual restore,它提供了一種方法,能夠將備份掛載爲活動的、功能齊全的數據庫,而無需物理恢復。

無論DBA是否喜歡,開發人員一般均可以訪問生產數據庫來執行特定的數據加載和更改。DBA和開發人員的共同責任是確保這些工做順利進行,從而避免致使須要採起剛纔所述行爲的問題。咱們將稍後在第6級—處理批量操做中討論這個主題。

固然,所需修復行動的性質取決於不良交易。若是表「意外丟失」,那麼極可能你將使用備用路由執行恢復。在其餘時候,你可能只須要建立一個腳原本「反轉」惡意修改便可。

若是損壞隻影響到單個列或有限數量的行,那麼可使用SQL Data Compare等工具做爲替代,它能夠直接與備份文件進行比較,並能夠進行行級恢復。

或者,若是您運行SQL Server 2005企業版(或更高版本),可使用最近的數據庫快照,則能夠對快照運行查詢,以便在查看數據庫快照時查看數據,而後寫一個更新或插入命令將數據從數據庫快照提取到實時源數據庫。

最後,做爲最後一種手段,一個專門的日誌讀取工具可能幫助你逆轉事務的影響,儘管我不知道SQL Server 2005及更高版本中的是否能夠進行可靠工做。

總結

在這個級別中,咱們介紹了在徹底恢復模式下運行的數據庫備份和恢復日誌文件的基礎知識,這將是許多生產數據庫的標準。

對於大多數DBA來講,執行時間點恢復的需求不多,可是若是有必要,那麼執行時間點恢復很是重要;DBA的聲譽也是取決於它。

在損壞、驅動器故障等狀況下,若是幸運的話,時間點恢復可能涉及備份事務日誌的尾部並恢復故障點的能力。若是事務日誌不可用,或者你正在恢復以使得在「很差事務」發生以前恢復到某個時間點,那麼狀況將變得更加複雜,但但願本步驟中介紹的一些技術將有所幫助。

資源:

TransactionLogStairway_Level5_Code.zip

本文是SQL Server Stairway中的事務日誌管理的一部分

註冊咱們的RSS訂閱,當咱們在階級上發佈一個新級別時,您就會獲得通知!

相關文章
相關標籤/搜索