程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> SQL Server 2005災難恢復方法和步驟

SQL Server 2005災難恢復方法和步驟

編輯:關於SqlServer
SQL Server 2005在實現高可用性和災難恢復方面給我們提供了很多種選擇。比技術本身更重要的是拿出適當的程序,這是因為我們要管理不同的災難恢復方案。我們應該如何拿出程序來管理多種多樣的災難恢復場景呢?

專家解答

這一系列文章將探討不同的災難恢復場景和涉及你的恢復計劃的程序。考慮到你的SQL Server 2005數據庫中的災難恢復選項,你應該包含盡可能多的技術,因為如果災難發生時你將會有很多種選擇來解決這個問題。盡管擁有這些技術被證實是很重要的,但是它也是一個伴隨著使整個程序更加有效的過程。在這篇文章裡,讓我們來看看一個簡單的場景,那就是在發生數據庫備份的5個小時後,一個用戶不小心刪除了一張表。從一個數據庫備份中恢復意味著失去5小時的數據。而對於大多數的公司來說,比起失去數據,他們更願意選擇失去時間。並且,如果這是一個非常大的數據庫,那麼將花很長一段時間來恢復和使它聯機。在將數據損失控制到最小的前提下,我們將考慮這種情況來建立一個程序方法,以此來盡快地恢復數據庫。我們將使用Northwind數據庫來顯示這個過程。記住在進行以下步驟之前先把Northwind中的數據庫恢復模式改成FULL。

(1) 確保你有一個好的備份

針對上面的場景,我們假設你有一個每天早上6:00運行的備份,並且沒有一個定期創建的數據庫快照。你的數據庫被配置成使用一個單一的MDF和LDF文件,這個文件對災難恢復不太適用。讓我們在Northwind數據庫中創建一個全數據庫備份,它將是數據庫恢復的起始點。以下是代碼:

USE master
  GO
  BACKUP DATABASE Northwind
  TO DISK = N'D:\DBBackup\NorthwindBackup.bak'
  WITH NAME = N'Full Database Backup', DESCRIPTION = 'Starting point for recovery',
  INIT, STATS = 10
  GO

從Northwind數據庫模式中,你很難刪除Products, Orders和Customers表,這是因為有其他表比如Order Details表的外碼約束限制。但我敢打賭你可以輕易地刪除Order Details表。接下來,我們來模擬在大約上午11:00時刪除這張表的災難情景。
 
 DROP TABLE [Order Details]

(2) 包含發生的問題

由於這個數據庫只有一個單一的MDF和LDF文件,我們不可能做很多操作。我們所能做的就是通過把它設置成有限制的用戶模式來使數據庫脫機。

USE master
  GO
  ALTER DATABASE Northwind
  SET RESTRICTED_USER
  WITH ROLLBACK IMMEDIATE
  GO

這將很有效地使數據庫脫機,停止所有活動的連接。這是分秒必爭的時刻,我們需要采取行動。當進行到下面的步驟時,請牢記你的RPO和RTO。

(3) 備份事務日志

一個好的數據庫管理員應該知道當災難來臨時,首先要做的是備份事務日志 – 假設你的數據庫被設置成全數據庫備份。這是為了確保在上次備份之後你還保存所有活動的事務。在我們的場景中,由於上次的備份 – 全備份,在這個例子中 – 發生於早上6:00。

BACKUP LOG Northwind
  TO DISK = N'D:\DBBackup\NorthwindBackupLog.trn'
  WITH NAME = N'Transaction Log Backup'
  , DESCRIPTION = 'Getting everything to current point in time.',
  STATS = 10
  GO

(4)還原數據庫到一個已知的良好時間點

現在,任何用戶意外地刪除一張表或者在數據庫上造成一些破壞後都不會立即告訴你。有時候,你可能需要自己深入挖掘它,但是這需要花很多時間。由於我們想讓數據庫盡快地聯機,所以我們假設一個眾所周知的良好時間點,並且讓發掘在稍後的時間裡進行。在下面的腳本中,我將選擇在我的STOPAT參數中將早上 10:42設置成已知的良好時間點,一次達到展示的目的。

RESTORE DATABASE Northwind
  FROM DISK = N'D:\DBBackup\NorthwindBackup.bak'
  WITH NORECOVERY, RESTRICTED_USER
  GO
  RESTORE LOG Northwind
  FROM DISK = N'D:\DBBackup\NorthwindBackupLog.trn'
  WITH RESTRICTED_USER,
  STOPAT = '2008-09-23 10:42:44.00', RECOVERY
  -- use a "known good" point in time
  GO

雖然我們已經把數據庫恢復到一個已知的良好時間點,但是我們並沒有知道我們實際上到底失去了多少數據。我們需要找出在執行DROP TABLE語句之前執行最後的一個INSERT語句的准確時間,這樣我們才能恢復盡可能多的數據。但是由於我們需要盡可能快地使數據庫聯機,所以我們不想在數據庫上直接做這些。這正證明了接下來的步驟是有價值的。

你可以通過執行一個針對它的查詢來驗證刪除的表是否已經恢復。

SELECT *
  FROM Northwind.dbo.[Order Details]
  GO

(5)創建一個恢復點的快照

我們將創建一個還原數據庫的數據庫快照,以此來做進一步的處理。這個數據庫快照將是把數據恢復到執行DROP TABLE語句之前的准確時間的參考。

USE master
  GO
  CREATE DATABASE Northwind_RestorePointSnapshot
  ON
  ( NAME = N'Northwind',
  FILENAME = N'D:\DBBackup\NorthwindData_RestorePontSnapshot.snap')
  AS SNAPSHOT OF [Northwind]
  GO

依靠這個表模式,我們可以選擇讓它保持原狀,或者像我們對Order Details 表所做的那樣,或者多做一些操作。如果這張表有一個現有IDENTITY欄,我們需要在IDENTITY欄的最大值和需要恢復的行的假設數量之間創建一個間隙。這當然取決於在上發生的事務數目。要確定IDENTITY欄的最大值,你可以執行如下顯示的DBCC CHECKIDENT命令:

DBCC CHECKIDENT ('tableName')
 --Displays the number of rows you have for the restored table
 GO

這將返回IDENTITY列的最大值。讓我們假設這張表每天的事務數目大約是4000條記錄,我們可以在最大值和下一個值之間創建一個間隙。如果IDENTITY列的最大值是25000,我們需要將4000加到這個值中,並且再次執行帶有RESEED參數的DBCC CHECKIDENT命令(我們簡單假設你在一天之內可以恢復失去的數據,那就是值為400):

DBCC CHECKIDENT ('tableName', RESEED, 29000 )
  --Creates a gap of for the IDENTITY column to start the next value at 29000
  GO

(6)使數據庫聯機

一旦你已經成功做到上面的步驟,那麼就更改數據庫選項使它聯機並且允許用戶連接到數據庫和運行他們的應用程序。

USE master
  GO
  ALTER DATABASE Northwind
  SET MULTI_USER
  GO

現在數據庫已經重新聯機並且刪除的表已經恢復。雖然現在每個人都很開心,但是作為數據庫管理員,我們的工作不能就此止步。記住我們仍然需要恢復從已知良好時間點到執行DROP TABLE命令之前的缺失數據。這是我們能夠恢復盡可能多的數據的唯一途徑。盡管我們可以用一些第三方工具來讀取事務日志和通過重放這些事務來恢復數據,但是絕大多數人沒有使用這些工具的奢侈權利。所以我們下一個最好的方法是使用帶有STOPAT選項的RESTORE從句。這可能有些繁瑣,有時也很讓人有壓力,因為一個錯誤會讓你陷入重復地執行整個過程的狀態。我們所需要做的就是找出我們做備份的時間,直到事務日志備份結束。在我們的場景中,上次的備份在早上6:00,而你的已知良好時間點在早上10:42.44。因此,你可以從早上10:42.44開始執行帶有STOPAT選項的RESTORE命令,並且把STOPAT時間值改成可能一秒。如果你不是很確定上次備份發生的時間,你可以一直查詢MSDB數據庫。

SELECT *
  FROM msdb.dbo.backupset AS a
  INNER JOIN msdb.dbo.backupmediafamily AS b
  ON a.media_set_id = b.media_set_id
  WHERE database_name = 'Northwind'
  ORDER BY backup_finish_date

請注意backup_finish_date和type欄,因為這些欄將會讓你知道什麼時候你需要考慮RESTORE命令中的STOPAT值。

(7)用不同的名稱恢復另一個損壞數據庫的副本以便於研究

用不同的名稱來還願損壞數據庫的另一個副本可以讓我們致力於數據的還原,而不用擔心可用性,這是因為我們已經成功建立一個生產數據庫。你只要確定你為恢復數據庫選擇了不同的名稱和數據庫文件位置,或者你可以結束損壞已經建立的數據庫。我們將重復步驟四所做的,但是在這裡使用不同的名稱和數據文件位置。

RESTORE DATABASE Northwind_recover
  FROM DISK = N'D:\DBBackup\NorthwindBackup.bak'
  WITH MOVE N'Northwind' TO N'D:\DBBackup\NorthwindData_recover.mdf',
  MOVE N'Northwind_Log' TO N'D:\DBBackup\NorthwindLog_recover.ldf',
  STANDBY = N'D:\DBBackup\Northwind_UNDO.bak',
  STATS = 10
  GO
  RESTORE LOG Northwind_recover
  FROM DISK = N'D:\DBBackup\NorthwindBackupLog.trn'
  WITH STANDBY = N'D:\DBBackup\Northwind_UNDO.bak',
  STATS = 10, STOPAT = '2008-09-23 10:42:44.00'
  GO

記錄你的STOPAT參數值,因為這將是你在這個過程中使用到的最關鍵的參數。由於我們只是重復了步驟四的過程,我們肯定知道這個時候還沒有執行DROP TABLE命令。

(8)通過提高STOPAT參數值來還原事務日志

我們執行RESTORE LOG命令,通過一分鐘 – 從10:42:44.00到 10:43:44.00來增加STOPAT參數值。

RESTORE LOG Northwind_recover
  FROM DISK = N'D:\DBBackup\NorthwindBackupLog.trn'
  WITH STANDBY = N'D:\DBBackup\Northwind_UNDO.bak',
  STATS = 10, STOPAT = '2008-09-23 10:43:44.00'
  GO

這是它重復的部分。不要因為它確實繁瑣而感到煩惱。你可以通過1分鐘,5分鐘,10分鐘和記錄這些時間來增加這個值。記住在執行RESTORE LOG命令之後在刪除的對象上運行一個測試查詢。我建議在這個活動上創建一張表,這張表看起來像這樣:

TIMEOBJECT EXISTED?
  10:43:44.00YES
  10:48:44.00YES
  10:58:44.00YES
  11:03:44.00NO

有了這個信息,你就可以很肯定地知道這張表在10:58:44.00與 11:03:44.00之間被刪除。你可以重復步驟8,並且因為你已經在一個更小的時間間隔內操作,你可以在一分鐘甚至一秒內增加STOPAT參數值,如果你覺得自己過度關注STOPAT參數的時間值,那麼請返回帶有你在步驟八中記錄的列表信息的步驟七,使恢復過程更快進行。你只需要記住在上次的 RESTORE LOG語句中使用WITH RECOVERY選項,例如: 

RESTORE LOG Northwind_recover
  FROM DISK = N'D:\DBBackup\NorthwindBackupLog.trn'
  WITH STATS = 10, STOPAT = '2008-09-23 11:01:44.00', RECOVERY
  GO

一旦你設法把數據庫恢復到執行DROP TABLE命令之前,你就可以在生產數據庫上所做的還原和恢復所做的作一個比較。你可以用很多種方式實現這一點。由於我們已經有一個之前創建好的數據庫快照,所以我們也用它來做災難恢復。先前關於SQL Server 2005 tablediff命令行工具的方法可以讓你可以了解如何使用這個工具但是只強調你的源數據庫將是你恢復的那個數據庫,並且目的數據庫將是你的數據庫快照。這是為什麼你的數據庫快照被證實是很重要的,尤其是如果你處理不只是一個平常的對象。如果你不習慣用命令行工具,那麼可以參考一個由來自 SQLTeam.com的成員創建的GUI版本。你可能也想確定這些並且把它放在你的DBA工具欄中。

你也可以執行一個INSERT/SELECT操作,在基於恢復數據庫的一個查詢的生產數據庫上插入紀錄。因為我們的Order Details表沒有IDENTITY欄,所以可以通過在一張臨時表中插入紀錄和使用ROW_NUMBER()函數來自己創建這一欄。

--This inserts records in a temporary table and assigns a dummy identity value for reference
  SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS ROWID, *
  INTO Northwind_recover.dbo.OrderDetailsRecover
  FROM [Order Details]
  --This inserts recovered records from the recovered database into the production database based on
  --the dummy identity valuewe have assigned for reference
  INSERT INTO Northwind.dbo.[Order Details] (OrderID,ProductId,UnitPrice,Quantity,Discount)
  SELECT OrderID,ProductId,UnitPrice,Quantity,Discount
  FROM Northwind_recover.dbo.OrderDetailsRecover
  WHERE ROWID>
  (
  SELECT COUNT(*)
  FROM Northwind_RestorePointSnapShot.dbo.[Order Details]
  )

請注意,我們使用數據庫快照來識別我們所設法還原的和我們所恢復的區別。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved