1. 程式人生 > >翻譯《Stairway to SQL Server Replication: Level 5- Managing the Log in Full Recovery Mode》 SQL Server事務日誌管理的進階,第5級:在完全恢復模式下管理日誌

翻譯《Stairway to SQL Server Replication: Level 5- Managing the Log in Full Recovery Mode》 SQL Server事務日誌管理的進階,第5級:在完全恢復模式下管理日誌

SQL Server事務日誌管理的進階,第5級:在完全恢復模式下管理日誌

SQL Server事務日誌管理的進階,第5級:在完全恢復模式下管理日誌

作者:託尼·戴維斯(Tony Davis)

時間:2012年1月27日

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

 

該系列

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

當事情進展順利時,不需要特別注意事務日誌是做什麼的或者它是如何工作的。您只需要確信每個資料庫都有正確的備份機制。當出現問題時,瞭解事務日誌對於採取糾正措施非常重要,特別是在需要及時恢復資料庫時更是如此。Tony Davis給出了每個DBA都應該知道的適當的細節級別。

 

在這一級別中,我們將回顧在完全恢復模式下工作時進行日誌備份的原因和方法,以及如何使用這些日誌備份檔案與完全資料庫備份一起執行資料庫還原。完全恢復模式支援將資料庫恢復到可用日誌備份中的任何時間點,並且,假設可以在失敗發生之前執行最後一次提交事務的時間之前執行尾日誌備份。

 

什麼記錄?

在FULL恢復模式下,所有操作都被完全記錄。對於插入、更新和刪除操作,這意味著對於修改的每一行,都會有一個日誌記錄,描述執行該語句的事務的ID、該事務何時開始和結束、更改了哪些頁面、更改了哪些資料等等。

 

在FULL恢復模式下工作時,可以最低限度記錄SELECT INTO、BULK INSERT和CREATE INDEX的操作仍然是完全記錄的,但操作方式略有不同。受這些操作影響的行不會單獨記錄;相反,只有資料庫頁面在被填充時才會被記錄下來。這減少了此類操作的日誌記錄,同時確保仍然存在執行回滾、重做和時間點恢復所需的相同資訊。Kalen Delaney發表了一些關於SELECT INTO  (http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/15/ what-gets-logge-forsel-into .aspx)和索引(http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/08/what-gets-logge-forindex -rebuilds.aspx)操作的日誌記錄的研究,包括FULL和BULK_LOGGED恢復模式。在BULK_LOGGED模式下工作時,最低日誌記錄操作的日誌記錄差異將在第6級-在批量日誌恢復模式下管理日誌中進行更詳細的討論。

 

為什麼備份事務日誌?

在完全恢復模式下,只有日誌備份才能導致日誌被截斷。因此,事務日誌將儲存自上次備份事務日誌以來執行的事務的完整記錄。由於所有操作都已被完全記錄,所以日誌檔案在繁忙的系統中可以非常大、非常快地增長。

 

因此,在完全恢復模式下工作時,除了執行完全備份和(可選的)差異備份之外,還必須執行常規事務日誌備份。許多新手或兼職dba在資料庫上執行完整備份,但不執行事務日誌備份。因此,事務日誌不會被截斷,它會不斷增長,直到它所在的驅動器耗盡磁碟空間,導致SQL Server停止工作。

 

日誌的截斷將在日誌備份完成後立即發生,假設自上次備份以來已經發生了檢查點,並且沒有其他因素延遲截斷,例如資料備份或還原操作。有關可能延遲可恢復的VLFs截斷的所有因素,以及保持大量日誌活動(否則不需要)的因素,如流氓的、長時間執行的未提交事務或資料庫映象或複製程序,請參見http://msdn.microsoft.com/en-gb/library/ms345414.aspx。

 

事務日誌的COPY_ONLY備份

事務日誌的COPY_ONLY備份不截斷事務日誌。一個COPY_ONLY日誌備份存在於普通日誌備份方案之外;它不會破壞日誌備份鏈。

 

簡而言之,事務日誌備份執行允許恢復和恢復到上一個時間點的雙重目的,以及控制事務日誌的大小。與事務日誌相關的問題最常見的原因可能是在完全恢復模式下工作,不進行日誌備份,或者不頻繁地進行日誌備份以控制事務日誌檔案的大小。

 

如果您不確定是否在給定的資料庫上執行事務日誌備份,那麼您可以使用類似於清單5.1所示的查詢,簡單地查詢MSDB資料庫中的反備份表。

 

USE msdb ; SELECT   backup_set_id ,           backup_start_date ,           backup_finish_date ,           backup_size ,           recovery_model ,           [type] FROM     dbo.backupset WHERE    database_name = 'TestDB'

清單5.1:是否進行日誌備份?

 在type列中,D表示資料庫備份,L表示日誌備份,I表示差異備份。

 請注意,由於可以在不影響備份和恢復行為的情況下對這個反備份表中的資料進行操作,因此您可能希望通過查詢sys來驗證從這個查詢中得到的結果。database_recovery_status檢視last_log_backup_lsn(請參見清單3.5)或sys的值。資料庫表中檢視log_reuse_wait_desc的值(如果需要備份,將返回LOG_BACKUP)。

 

如何備份事務日誌

正如前面所討論的,如果不首先進行至少一次完整備份,就不可能執行事務日誌備份。事實上,如果您的資料庫處於完全恢復模式,但是從來沒有備份過,那麼它實際上不會在完全恢復模式下工作。在執行第一次完整備份之前,資料庫將處於自動截斷模式。

 

所有資料庫備份(完整備份、日誌備份或其他備份)都使用BACKUP命令執行。該命令接受許多選項,這些選項在這裡有記錄:http://msdn.microsoft.com/en-us/library/ms186865.aspx。然而,在最基本的情況下(通常是這樣使用的),對磁碟執行完整備份的命令如下:

 

如果這是要執行的第一個備份,則資料庫名。bak檔案將建立在指定的目錄。如果已經存在這樣的檔案,那麼預設行為是將後續備份追加到該檔案。要覆蓋此行為,並規定應該覆蓋任何現有檔案,我們可以使用INIT選項,如下所示:

 

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

 

在每次常規(如每日)全面備份之後,會有頻繁(如每小時)的日誌備份,基本命令非常類似:

 

 

 儲存日誌備份

顯然,備份的資料和日誌檔案不應該儲存在承載活動檔案的同一驅動器上。如果該驅動器發生硬體故障,那麼您的所有副本將與活動檔案一起丟失,備份將是徒勞的。檔案應該備份到單獨的裝置,或者備份到本地映象驅動器。

 

日誌備份頻率

如前所述,您可能每15分鐘進行一次日誌備份,甚至可能更頻繁。在這種情況下,為了避免需要還原大量的事務日誌檔案,您可以選擇採用一種由完全備份組成的備份方案,其中穿插了差異備份和事務日誌備份。

 

在現實中,備份方案通常是理想和實際之間的折衷,是對資料丟失的真實風險的評估,以及它將給公司帶來的成本,以及降低這種風險所涉及的成本之間的折衷。許多非常重要的業務應用程式使用稍微簡單一些但仍然嚴格的備份方案,可能涉及定期的夜間完整備份和每小時的事務日誌備份。

 

日誌備份的頻率也可以由資料庫所涉及的事務的數量決定。對於非常繁忙的資料庫,可能需要經常備份以便控制日誌的大小。

 

沒有簡單的方法來計算多久做一次日誌備份。大多數dba將對日誌備份的頻率進行最佳估計,然後觀察檔案的增長特徵,然後根據需要調整備份方案,以防止檔案過大。

 

日誌鏈和如何打破它

如前所述,如果不首先進行至少一次完整備份,則不可能執行事務日誌備份。為了恢復一個數據庫的時間點,要麼結束的一個特定的日誌備份或時間點在一個特定的日誌備份,一定存在一個完整的日誌記錄,從第一個日誌備份後,一個完整的(或微分備份),直到故障點。這就是所謂的對數鏈。

 

有許多方法可以破壞日誌鏈,如果這樣做,就意味著只能將資料庫恢復到破壞日誌鏈的事件發生之前進行日誌備份的時間。簡而言之,如果您關心恢復資料的能力,那麼斷開鏈不是一個好主意。兩種最常見的方法打破鏈包括:

  • 事務日誌備份檔案的丟失或損壞—您將只能恢復到上一次良好的日誌備份。日誌鏈將在下一個良好的完全備份或差異備份時再次啟動。
  •  切換到簡單恢復模式—如果您曾經從完全恢復模式切換到簡單恢復模式,這將破壞日誌鏈,因為會觸發檢查點,事務日誌可以立即被截斷。當您返回到FULL模式時,您將需要另一個完整備份來重新啟動日誌鏈。事實上,在進行完整備份之前,資料庫將保持自動截斷模式,並且無法備份日誌檔案。

 

在SQL Server 2008之前,有兩個命令,即帶有NO_LOG的備份日誌或帶有TRUNCATE_ONLY的備份日誌(它們在功能上是等效的),當發出這些命令時,將強制截斷日誌檔案,從而打破日誌鏈。您不應該在任何版本的SQL Server中發出這些命令,但是我在這裡提到了它們,因為在嘗試處理“失控的日誌檔案”時,它們仍然會被粗心的人使用,而不理解它對恢復資料庫能力的影響。請參閱第8級-幫助,我的日誌已滿,瞭解更多細節。

 

尾日誌備份

只要您有一個最近的完整備份和一個完整的日誌鏈,您就可以將資料庫恢復到它在任何失敗之前的最後日誌備份結束時的狀態。但是,假設您每小時進行事務日誌備份,並且在下午1:45發生故障。你可能會損失45分鐘的資料;事實上,如果失敗是災難性的,以至於實時事務日誌是不可檢索的,那麼這就是您將丟失的資料量。

 

但是,有時即使資料檔案不可用,仍然可以使用實時事務日誌,特別是如果事務日誌包含在單獨的專用驅動器上。如果是這樣,應該備份實時事務日誌,即對上次日誌備份之後生成的日誌記錄執行最後一次備份。這將捕獲活動日誌檔案中到故障點為止的其餘日誌記錄。這稱為尾部日誌備份,是開始恢復和恢復操作之前應該執行的最後一個操作。

 

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

      如果資料檔案由於資料庫故障而不可用,並且日誌的尾部包含最少日誌記錄的操作,那 麼將不 可能執行尾部日誌備份,因為這將需要訪問資料檔案中更改的資料區段。第6 級將更詳細地介紹這一點,以批量日誌模式管理事務日誌。

 

如果您希望恢復的資料庫是聯機的,那麼日誌的尾部將備份如下:

 

NORECOVERY選項將資料庫置於恢復狀態,並假設您希望執行的下一個操作是恢復。如果資料庫處於離線狀態且無法啟動,您仍然應該嘗試像剛才描述的那樣備份日誌尾部(儘管可以省略NORECOVERY選項,因為沒有事務在進行中)。

 

如果您確定日誌檔案已經損壞,那麼文件建議,作為最後一種方法,您可以嘗試使用以下方法進行尾部日誌備份:

 

如果主資料庫和資料檔案損壞,但日誌可用,Microsoft建議重新構建主資料庫,然後備份最後一個活動日誌。但是,這些主題超出了這個樓梯的範圍,我建議您參閱文件瞭解更多細節。見http://msdn.microsoft.com/en-us/library/ms190952.aspx。

 

執行恢復和恢復

在執行了尾日誌備份之後,如果可能,下一步是恢復最後一個完整備份(如果合適的話,接下來是差分備份),然後恢復完整的日誌備份檔案序列,包括尾日誌備份。這個還原操作序列的基本語法如下:

 

如果在恢復時省略了WITH NORECOVERY選項,那麼預設情況下,恢復命令將繼續恢復。換句話說,SQL Server將嘗試協調資料和日誌檔案,前滾已完成的事務,然後根據需要回滾未完成的事務。通過使用NORECOVERY指定,我們指示SQL Server輸入恢復序列,在執行任何回滾之前,必須前滾更多操作。在還原序列中還原最後一個備份後,資料庫可以恢復如下:

 

一個常見的需求是將資料庫恢復到不同的位置,在這種情況下,您可以作為恢復過程的一部分簡單地移動檔案,如下所述:http://msdn.microsoft.com/en-us/library/ms190255.aspx。

 

資料庫故障後的恢復

下面的示例描述如何在資料庫資料檔案不再可訪問的情況下恢復資料庫。

 

完全恢復到故障點

假設“活動”事務日誌可以在資料庫故障(可能是由硬體故障引起的)之後到達,那麼從理論上講,應該可以通過以下步驟恢復和恢復資料庫,直至故障點:

 

1.備份日誌的尾部

2.恢復最近的完整備份(加上差異,如果適用)

3.依次恢復在完全備份(或差異備份)之後執行並在失敗之前完成的每個事務日誌備份

4.還原尾日誌備份

5.恢復資料庫

 

線上書籍中的許多示例演示了從“備份集”(也就是儲存所有備份的單個“裝置”)恢復和恢復。實際上,這意味著,當備份到磁碟時,備份裝置是位於磁碟上某個位置的單個.bak檔案。

 

因此,例如,清單5.2中顯示的簡單示例使用一個由一個完整備份和一個事務日誌備份組成的備份集,並展示瞭如何執行完整還原。為了執行這段程式碼,首先需要重新建立TestDB資料庫,然後插入一些示例資料行(為了方便起見,這個指令碼是CreateAndPopulateTestDB.sql,包含在這個級別的程式碼下載中)。您還需要在資料庫伺服器的本地C:驅動器上建立一個“備份”目錄,或者根據需要修改檔案路徑。

 

-- Perform a full backup of the Test database -- The WITH FORMAT option starts a new  backup set -- Be careful, as  it will overwrite any existing sets -- The full backup becomes the first file in  the set BACKUP DATABASE TestDB TO DISK = 'C:\Backups\TestDB.bak' WITH FORMAT; GO   -- Perform a transaction log backup of the Test database -- This is  the second file in  the set BACKUP Log TestDB TO DISK = 'C:\Backups\TestDB.bak' GO   -- ....<FAILURE OCCURS HERE>....   -- The RESTORE HEADERONLY command is  optional. -- It simply confirms the files that comprise -- the current set RESTORE HEADERONLY FROM DISK = 'C:\Backups\TestDB.bak' GO   -- Back up the tail of the log to prepare for  restore -- This will become the third file of the bakup set BACKUP Log TestDB TO DISK = 'C:\Backups\TestDB.bak' WITH NORECOVERY; GO   -- Restore the full backup RESTORE DATABASE TestDB FROM DISK = 'C:\Backups\TestDB.bak' WITH FILE=1, NORECOVERY;   -- Apply the transaction log backup RESTORE LOG TestDB FROM DISK = 'C:\Backups\TestDB.bak' WITH FILE=2, NORECOVERY;   -- Apply the tail log backup RESTORE LOG TestDB FROM DISK = 'C:\Backups\TestDB.bak' WITH FILE=3, NORECOVERY;   -- Recover the database RESTORE DATABASE TestDB WITH RECOVERY; GO

  

清單5.2:備份到備份集並從中恢復;不推薦

 

然而,使用備份集似乎是資料庫備份到磁帶時代的遺留問題。當備份到磁碟時,使用這種方案是一個壞主意,因為,當然,備份檔案將迅速增長到非常大。

 

在實踐中,更常見的情況是,每個完整的備份和事務日誌備份檔案都將單獨命名,並且可能會標記備份的時間和日期。例如,大多數第三方備份工具、流行的社群生成指令碼,以及SSMS中的維護計劃嚮導/設計器,都將建立單獨的日期戳檔案,例如AdventureWorks_FULL_20080904_000001.bak。

 

因此,更常見的備份和恢復方案將使用惟一命名的備份,如清單5.3所示。

 

複製程式碼
USE master;
BACKUP DATABASE TestDB
TO DISK ='C:\Backups\TestDB.bak'
WITH INIT;
GO

-- Perform a transaction log backup of the Test database
BACKUP Log TestDB
TO DISK ='C:\Backups\TestDB_log.bak'
WITH INIT;
GO

-- ....<FAILURE OCCURS HERE>....

-- Back up the tail of the log to prepare for restore
BACKUP Log TestDB
TO DISK ='C:\Backups\TestDB_taillog.bak'
WITH NORECOVERY, INIT;
GO

-- Restore the full backup
RESTORE DATABASE TestDB
FROM DISK = 'C:\Backups\TestDB.bak'
WITH NORECOVERY;

-- Apply the transaction log backup
RESTORE LOG TestDB
FROM DISK = 'C:\Backups\TestDB_log.bak'
WITH NORECOVERY;

-- Apply the tail log backup
RESTORE LOG TestDB
FROM DISK = 'C:\Backups\TestDB_taillog.bak'
WITH NORECOVERY;

-- Recover the database
RESTORE DATABASE TestDB
WITH RECOVERY;
GO
複製程式碼

 

清單5.3:備份和恢復名稱獨特的備份檔案

 

及時恢復到上次良好的日誌備份

不幸的是,有時可能無法執行完全恢復;例如,如果活動事務日誌由於故障而不可用。在這種情況下,我們只需要恢復到最近一次日誌備份的末尾。需要為這種可能發生的情況做好準備,即包含事務日誌的驅動器出現故障,這決定了日誌備份的頻率。如果您每15分鐘備份一次,那麼您將面臨15分鐘資料丟失的風險。

 

假設我們已經執行了清單5.4中所示的備份序列。為了演示,我們覆蓋了以前的備份檔案,而且備份序列顯然比實際要短得多。

 

複製程式碼
-- FULL BACKUP at 2AM
USE master ;
BACKUP DATABASE TestDB
TO DISK = 'C:\Backups\TestDB.bak'
WITH INIT ;
GO

-- LOG BACKUP 1 at 2.15 AM
USE master ;
BACKUP LOG TestDB
TO DISK = 'C:\Backups\TestDB_log.bak'
WITH INIT ;
GO

-- LOG BACKUP 2 at 2.30 AM
USE master ;
BACKUP LOG TestDB
TO DISK = 'C:\Backups\TestDB_log2.bak'
WITH INIT ;
GO
複製程式碼

 

 清單5.4:一個簡短的日誌備份系列

 

如果在凌晨2:30之後不久發生災難性故障,我們可能需要將資料庫恢復到日誌備份2結束時的狀態,即凌晨2:30。

 

這個例子中的恢復序列與我們之前在清單5.3中看到的非常相似,但是由於不可能進行尾部備份,而且我們只能恢復到某個點,因此需要使用STOPAT選項,如清單5.5所示。

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --RESTORE Full backup RESTORE DATABASE TestDB FROM DISK =  'C:\Backups\TestDB.bak' WITH NORECOVERY;   --RESTORE Log file 1 RESTORE LOG TestDB FROM DISK =  'C:\Backups\TestDB_log.bak' WITH NORECOVERY, STOPAT =  'Jan 01, 2020 12:00 AM' ;   --RESTORE Log file 2 RESTORE LOG TestDB FROM DISK =  'C:\Backups\TestDB_Log2.bak' WITH NORECOVERY, STOPAT =  'Jan 01, 2020 12:00 AM' ;   --Recover the database RESTORE DATABASE TestDB WITH RECOVERY; GO

  

清單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。

 

 在“錯誤的事務”後恢復

在任何資料庫失敗的上下文之外,可能需要恢復資料庫備份和事務日誌,以便在進行錯誤的資料修改(如刪除或截斷表)之前將資料庫及時返回到特定的時間點。

 

你對這種情況的反應將取決於問題的性質。如果可能,您可以斷開所有使用者與資料庫的連線(在通知他們之後),並評估剛剛發生的事情的影響。在某些情況下,您可能需要估計問題發生的時間,然後使用時間恢復點對資料庫和日誌進行全面恢復。恢復完成後,您必須通知使用者一些事務可能已經丟失,並請求原諒。

 

當然,您通常不能以這種方式中斷正常的業務操作,以修復意外的資料丟失。由於live資料庫仍在執行和訪問中,您可以嘗試在備用模式下恢復資料庫的備份。這允許恢復更多的日誌備份,但與使用NORECOVERY不同的是,資料庫仍然是可讀的。恢復方案可能是這樣的:

 

1.在備用模式下,在活動資料庫旁邊恢復資料庫的備份

2.將日誌前滾到錯誤事務發生之前的位置,資料丟失。

3.將丟失的資料複製到活動資料庫,並刪除恢復的副本

 

當然,這個過程不一定是直接的,而且可能相當耗時。除非您購買了專門的日誌讀取工具,並且可以直接查詢日誌備份,否則前滾日誌可能意味著一系列艱苦的步驟,包括恢復日誌、檢查資料、進一步恢復等等,直到您確切地知道錯誤事務發生在哪裡。第3步也很困難,因為您將向活動系統引入資料,而這些資料不一定與資料庫的當前狀態一致,因此可能存在引用完整性問題。

 

讓我們看一個實現上面步驟1和步驟2的示例。首先,讓我們從頭開始執行CreateAndPopulateTestDB。重新建立TestDB資料庫的sql指令碼,並將10行測試資料插入新的LogTest表中。在清單5.6中,我們簡單地做了一個完整的資料庫備份(覆蓋所有以前的備份檔案)。如果還沒有建立“備份”目錄,則需要建立“備份”目錄,或者根據需要調整路徑。

 

-- full backup of the database
BACKUP DATABASE TestDB
TO DISK ='C:\Backups\TestDB.bak'
WITH INIT;
GO

 

清單5.6:TestDB的完整備份

 

然後,我們將一行新的資料插入LogTest表。

 

複製程式碼
USE TestDB
GO
INSERT INTO [TestDB].[dbo].[LogTest]
           ([SomeInt]
           ,[SomeLetters2])
     VALUES
           (66666,
           'ST')
           
SELECT * FROM dbo.LogTest
複製程式碼

 

 清單5.7:向TestDB插入第11行

 

因此,現在我們有了一個LogTest表中有11行活動TestDB資料庫,以及一個有10行備份的版本。現在讓我們在日誌備份中捕獲額外的修改,如清單5.8所示。

 

複製程式碼
USE master
GO
BACKUP Log TestDB
TO DISK ='C:\Backups\TestDB_log.bak'
WITH INIT;
GO
複製程式碼

 

清單5.8:TestDB的日誌備份

 

現在,我們要模擬一個錯誤的“壞事務”,只需刪除LogTest表,然後執行最後的日誌備份。

 

複製程式碼
USE TestDB
GO
DROP TABLE dbo.LogTest ;

USE master
GO
BACKUP Log TestDB
TO DISK ='C:\Backups\TestDB_log2.bak'
WITH INIT;
GO
複製程式碼

 

清單5.9:災難!

 

為了在不中斷正常業務操作的情況下試圖檢索丟失的資料,我們將以備用模式恢復TestDB資料庫的副本。備用資料庫的資料和日誌檔案(稱為ANewTestDB)被移動到一個“備用”目錄(您需要預先建立這個目錄)。

 

複製程式碼
-- restore a copy of the TestDB database, called
-- ANewTestDB, in STANDBY mode
USE master ;
GO
RESTORE DATABASE ANewTestDB
   FROM DISK ='C:\Backups\TestDB.bak'
   WITH STANDBY='C:\Backups\ANEWTestDB.bak',
   MOVE 'TestDB_dat' TO 'C:\Standby\ANewTestDB.mdf', 
   MOVE 'TestDB_log' TO 'C:\Standby\ANewTestDB.ldf'
GO
複製程式碼

 

 清單5.10:在備用模式下恢復TestDB的副本

 

現在我們有了一個新的資料庫,名為ANewTestDB,它處於“備用/只讀”模式,如圖5.1所示。

 

圖5.1:備用資料庫

 

對ANewTestDB資料庫中的LogTest表的查詢將顯示10行。但是,我們希望將表恢復到它被錯誤刪除之前的狀態。因此,下一步是將日誌備份還原到備用資料庫。

 

USE master
GO
RESTORE LOG ANewTestDB
FROM DISK = 'C:\Backups\TestDB_log.bak'
   WITH STANDBY='C:\Backups\ANewTestDB_log.bak'

清單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中的事務日誌管理的一部分

SQL Server事務日誌管理的進階,第5級:在完全恢復模式下管理日誌

作者:託尼·戴維斯(Tony Davis)

時間:2012年1月27日

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

 

該系列

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

當事情進展順利時,不需要特別注意事務日誌是做什麼的或者它是如何工作的。您只需要確信每個資料庫都有正確的備份機制。當出現問題時,瞭解事務日誌對於採取糾正措施非常重要,特別是在需要及時恢復資料庫時更是如此。Tony Davis給出了每個DBA都應該知道的適當的細節級別。

 

在這一級別中,我們將回顧在完全恢復模式下工作時進行日誌備份的原因和方法,以及如何使用這些日誌備份檔案與完全資料庫備份一起執行資料庫還原。完全恢復模式支援將資料庫恢復到可用日誌備份中的任何時間點,並且,假設可以在失敗發生之前執行最後一次提交事務的時間之前執行尾日誌備份。

 

什麼記錄?

在FULL恢復模式下,所有操作都被完全記錄。對於插入、更新和刪除操作,這意味著對於修改的每一行,都會有一個日誌記錄,描述執行該語句的事務的ID、該事務何時開始和結束、更改了哪些頁面、更改了哪些資料等等。

 

在FULL恢復模式下工作時,可以最低限度記錄SELECT INTO、BULK INSERT和CREATE INDEX的操作仍然是完全記錄的,但操作方式略有不同。受這些操作影響的行不會單獨記錄;相反,只有資料庫頁面在被填充時才會被記錄下來。這減少了此類操作的日誌記錄,同時確保仍然存在執行回滾、重做和時間點恢復所需的相同資訊。Kalen Delaney發表了一些關於SELECT INTO  (http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/15/ what-gets-logge-forsel-into .aspx)和索引(http://sqlblog.com/blogs/kalen_delaney/archive/2011/03/08/what-gets-logge-forindex -rebuilds.aspx)操作的日誌記錄的研究,包括FULL和BULK_LOGGED恢復模式。在BULK_LOGGED模式下工作時,最低日誌記錄操作的日誌記錄差異將在第6級-在批量日誌恢復模式下管理日誌中進行更詳細的討論。

 

為什麼備份事務日誌?

在完全恢復模式下,只有日誌備份才能導致日誌被截斷。因此,事務日誌將儲存自上次備份事務日誌以來執行的事務的完整記錄。由於所有操作都已被完全記錄,所以日誌檔案在繁忙的系統中可以非常大、非常快地增長。

 

因此,在完全恢復模式下工作時,除了執行完全備份和(可選的)差異備份之外,還必須執行常規事務日誌備份。許多新手或兼職dba在資料庫上執行完整備份,但不執行事務日誌備份。因此,事務日誌不會被截斷,它會不斷增長,直到它所在的驅動器耗盡磁碟空間,導致SQL Server停止工作。

 

日誌的截斷將在日誌備份完成後立即發生,假設自上次備份以來已經發生了檢查點,並且沒有其他因素延遲截斷,例如資料備份或還原操作。有關可能延遲可恢復的VLFs截斷的所有因素,以及保持大量日誌活動(否則不需要)的因素,如流氓的、長時間執行的未提交事務或資料庫映象或複製程序,請參見http://msdn.microsoft.com/en-gb/library/ms345414.aspx。

 

事務日誌的COPY_ONLY備份

事務日誌的COPY_ONLY備份不截斷事務日誌。一個COPY_ONLY日誌備份存在於普通日誌備份方案之外;它不會破壞日誌備份鏈。

 

簡而言之,事務日誌備份執行允許恢復和恢復到上一個時間點的雙重目的,以及控制事務日誌的大小。與事務日誌相關的問題最常見的原因可能是在完全恢復模式下工作,不進行日誌備份,或者不頻繁地進行日誌備份以控制事務日誌檔案的大小。

 

如果您不確定是否在給定的資料庫上執行事務日誌備份,那麼您可以使用類似於清單5.1所示的查詢,簡單地查詢MSDB資料庫中的反備份表。

 

USE msdb ; SELECT   backup_set_id ,           backup_start_date ,           backup_finish_date ,           backup_size ,           recovery_model ,           [type] FROM     dbo.backupset WHERE    database_name = 'TestDB'

清單5.1:是否進行日誌備份?

 在type列中,D表示資料庫備份,L表示日誌備份,I表示差異備份。

 請注意,由於可以在不影響備份和恢復行為的情況下對這個反備份表中的資料進行操作,因此您可能希望通過查詢sys來驗證從這個查詢中得到的結果。database_recovery_status檢視last_log_backup_lsn(請參見清單3.5)或sys的值。資料庫表中檢視log_reuse_wait_desc的值(如果需要備份,將返回LOG_BACKUP)。

 

如何備份事務日誌

正如前面所討論的,如果不首先進行至少一次完整備份,就不可能執行事務日誌備份。事實上,如果您的資料庫處於完全恢復模式,但是從來沒有備份過,那麼它實際上不會在完全恢復模式下工作。在執行第一次完整備份之前,資料庫將處於自動截斷模式。

 

所有資料庫備份(完整備份、日誌備份或其他備份)都使用BACKUP命令執行。該命令接受許多選項,這些選項在這裡有記錄:http://msdn.microsoft.com/en-us/library/ms186865.aspx。然而,在最基本的情況下(通常是這樣使用的),對磁碟執行完整備份的命令如下:

 

如果這是要執行的第一個備份,則資料庫名。bak檔案將建立在指定的目錄。如果已經存在這樣的檔案,那麼預設行為是將後續備份追加到該檔案。要覆蓋此行為,並規定應該覆蓋任何現有檔案,我們可以使用INIT選項,如下所示:

 

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

 

在每次常規(如每日)全面備份之後,會有頻繁(如每小時)的日誌備份,基本命令非常類似:

 

 

 儲存日誌備份

顯然,備份的資料和日誌檔案不應該儲存在承載活動檔案的同一驅動器上。如果該驅動器發生硬體故障,那麼您的所有副本將與活動檔案一起丟失,備份將是徒勞的。檔案應該備份到單獨的裝置,或者備份到本地映象驅動器。

 

日誌備份頻率

如前所述,您可能每15分鐘進行一次日誌備份,甚至可能更頻繁。在這種情況下,為了避免需要還原大量的事務日誌檔案,您可以選擇採用一種由完全備份組成的備份方案,其中穿插了差異備份和事務日誌備份。

 

在現實中,備份方案通常是理想和實際之間的折衷,是對資料丟失的真實風險的評估,以及它將給公司帶來的成本,以及降低這種風險所涉及的成本之間的折衷。許多非常重要的業務應用程式使用稍微簡單一些但仍然嚴格的備份方案,可能涉及定期的夜間完整備份和每小時的事務日誌備份。

 

日誌備份的頻率也可以由資料庫所涉及的事務的數量決定。對於非常繁忙的資料庫,可能需要經常備份以便控制日誌的大小。

 

沒有簡單的方法來計算多久做一次日誌備份。大多數dba將對日誌備份的頻率進行最佳估計,然後觀察檔案的增長特徵,然後根據需要調整備份方案,以防止檔案過大。

 

日誌鏈和如何打破它

如前所述,如果不首先進行至少一次完整備份,則不可能執行事務日誌備份。為了恢復一個數據庫的時間點,要麼結束的一個特定的日誌備份或時間點在一個特定的日誌備份,一定存在一個完整的日誌記錄,從第一個日誌備份後,一個完整的(或微分備份),直到故障點。這就是所謂的對數鏈。

 

有許多方法可以破壞日誌鏈,如果這樣做,就意味著只能將資料庫恢復到破壞日誌鏈的事件發生之前進行日誌備份的時間。簡而言之,如果您關心恢復資料的能力,那麼斷開鏈不是一個好主意。兩種最常見的方法打破鏈包括:

  • 事務日誌備份檔案的丟失或損壞—您將只能恢復到上一次良好的日誌備份。日誌鏈將在下一個良好的完全備份或差異備份時再次啟動。
  •  切換到簡單恢復模式—如果您曾經從完全恢復模式切換到簡單恢復模式,這將破壞日誌鏈,因為會觸發檢查點,事務日誌可以立即被截斷。當您返回到FULL模式時,您將需要另一個完整備份來重新啟動日誌鏈。事實上,在進行完整備份之前,資料庫將保持自動截斷模式,並且無法備份日誌檔案。

 

在SQL Server 2008之前,有兩個命令,即帶有NO_LOG的備份日誌或帶有TRUNCATE_ONLY的備份日誌(它們在功能上是等效的),當發出這些命令時,將強制截斷日誌檔案,從而打破日誌鏈。您不應該在任何版本的SQL Server中發出這些命令,但是我在這裡提到了它們,因為在嘗試處理“失控的日誌檔案”時,它們仍然會被粗心的人使用,而不理解它對恢復資料庫能力的影響。請參閱第8級-幫助,我的日誌已滿,瞭解更多細節。

 

尾日誌備份

只要您有一個最近的完整備份和一個完整的日誌鏈,您就可以將資料庫恢復到它在任何失敗之前的最後日誌備份結束時的狀態。但是,假設您每小時進行事務日誌備份,並且在下午1:45發生故障。你可能會損失45分鐘的資料;事實上,如果失敗是災難性的,以至於實時事務日誌是不可檢索的,那麼這就是您將丟失的資料量。

 

但是,有時即使資料檔案不可用,仍然可以使用實時事務日誌,特別是如果事務日誌包含在單獨的專用驅動器上。如果是這樣,應該備份實時事務日誌,即對上次日誌備份之後生成的日誌記錄執行最後一次備份。這將捕獲活動日誌檔案中到故障點為止的其餘日誌記錄。這稱為尾部日誌備份,是開始恢復和恢復操作之前應該執行的最後一個操作。

 

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

      如果資料檔案由於資料庫故障而不可用,並且日誌的尾部包含最少日誌記錄的操作,那 麼將不 可能執行尾部日誌備份,因為這將需要訪問資料檔案中更改的資料區段。第6 級將更詳細地介紹這一點,以批量日誌模式管理事務日誌。

 

如果您希望恢復的資料庫是聯機的,那麼日誌的尾部將備份如下:

 

NORECOVERY選項將資料庫置於恢復狀態,並假設您希望執行的下一個操作是恢復。如果資料庫處於離線狀態且無法啟動,您仍然應該嘗試像剛才描述的那樣備份日誌尾部(儘管可以省略NORECOVERY選項,因為沒有事務在進行中)。

 

如果您確定日誌檔案已經損壞,那麼文件建議,作為最後一種方法,您可以嘗試使用以下方法進行尾部日誌備份:

 

如果主資料庫和資料檔案損壞,但日誌可用,Microsoft建議重新構建主資料庫,然後備份最後一個活動日誌。但是,這些主題超出了這個樓梯的範圍,我建議您參閱文件瞭解更多細節。見http://msdn.microsoft.com/en-us/library/ms190952.aspx。

 

執行恢復和恢復

在執行了尾日誌備份之後,如果可能,下一步是恢復最後一個完整備份(如果合適的話,接下來是差分備份),然後恢復完整的日誌備份檔案序列,包括尾日誌備份。這個還原操作序列的基本語法如下:

 

如果在恢復時省略了WITH NORECOVERY選項,那麼預設情況下,恢復命令將繼續恢復。換句話說,SQL Server將嘗試協調資料和日誌檔案,前滾已完成的事務,然後根據需要回滾未完成的事務。通過使用NORECOVERY指定,我們指示SQL Server輸入恢復序列,在執行任何回滾之前,必須前滾更多操作。在還原序列中還原最後一個備份後,資料庫可以恢復如下:

 

一個常見的需求是將資料庫恢復到不同的位置,在這種情況下,您可以作為恢復過程的一部分簡單地移動檔案,如下所述:http://msdn.microsoft.com/en-us/library/ms190255.aspx。

 

資料庫故障後的恢復

下面的示例描述如何在資料庫資料檔案不再可訪問的情況下恢復資料庫。

 

完全恢復到故障點

假設“活動”事務日誌可以在資料庫故障(可能是由硬體故障引起的)之後到達,那麼從理論上講,應該可以通過以下步驟恢復和恢復資料庫,直至故障點:

 

1.備份日誌的尾部

2.恢復最近的完整備份(加上差異,如果適用)

3.依次恢復在完全備份(或差異備份)之後執行並在失敗之前完成的每個事務日誌備份

4.還原尾日誌備份

5.恢復資料庫

 

線上書籍中的許多示例演示了從“備份集”(也就是儲存所有備份的單個“裝置”)恢復和恢復。實際上,這意味著,當備份到磁碟時,備份裝置是位於磁碟上某個位置的單個.bak檔案。

 

因此,例如,清單5.2中顯示的簡單示例使用一個由一個完整備份和一個事務日誌備份組成的備份集,並展示瞭如何執行完整還原。為了執行這段程式碼,首先需要重新建立TestDB資料庫,然後插入一些示例資料行(為了方便起見,這個指令碼是CreateAndPopulateTestDB.sql,包含在這個級別的程式碼下載中)。您還需要在資料庫伺服器的本地C:驅動器上建立一個“備份”目錄,或者根據需要修改檔案路徑。

 

-- Perform a full backup of the Test database -- The WITH FORMAT option starts a new  backup set -- Be careful, as  it will overwrite any existing sets

相關推薦

no