說明:災難恢複系列的文章是由 Robert Davis 寫的,發布在SQLSoldier, 個人認為挺不錯的,所以根據自己的理解,邊測試邊整理,並非直接翻譯,如有不準確,歡迎指正。
本篇進入資料庫災難恢複第五篇,從本篇開始,主要深入講述一些資料page損壞的問題,先從容易修複的非叢集索引開始。
通常,處理資料損毀的情況按三個步驟進行:
1.確定損壞(使用DBCC CHECKDB)
2.確定損壞的對象及物件類型(如索引頁、分配頁等)
3.確定適合的修複方法
確定損壞
當我們在做一些例行完整性檢查或者收到一些其它的錯誤或警告,如果有一個page損壞的資訊,不要直接就去處理這個頁面,應該先對資料庫運行DBCC CHECCKDB做一下全面檢查,以確定是不是其它頁面造成的。
使用DBCC CHECKDB可讓看到哪些page損壞,我們通過使用No_InfoMsgs選項過濾不需要的資訊,同時使用All_ErrorMsgs確保返回所有錯誤,為了可讀性,我們用TableResults 選項將其結果格式化成表,如:
DBCC CheckDB(AdventureWorksDW2012) With No_InfoMsgs, All_ErrorMsgs, TableResults;
從結果可以看到返回了一些錯誤,有些是相同的,需要我們自己找出哪些是真的錯誤,然後通過具體的錯誤資訊找出對象id,索引id,分區id,配置單位id,檔案及頁面(object ID, index ID, partition ID, allocation unit ID, file, and page.)。
確定損壞的對象及物件類型
在執行DBCC CHECKDB之後,我們也可以通過msdb的suspect_pages去確定損壞資訊,這個表每一行記錄一個損壞的page,不過這個表沒有對象id和索引id,只有資料庫id、檔案號、資料頁id,如果需要更詳細資料,需要用DBCC PAGE去查看了。在這裡我們不用這個方法,因為之前的DBCC CHECKDB中已經有這些資訊。
SELECT DB_NAME(database_id),[file_id],page_id,CASE event_typeWHEN 1 THEN '823 or 824 or Torn Page'WHEN 2 THEN 'Bad Checksum'WHEN 3 THEN 'Torn Page'WHEN 4 THEN 'Restored'WHEN 5 THEN 'Repaired (DBCC)'WHEN 7 THEN 'Deallocated (DBCC)'END,error_count,last_update_dateFROM msdb..suspect_pages
索引ID對應索引類型:
ID 0 = heap(堆)
ID 1 = clustered index(叢集索引)
ID > 1 = nonclustered index(非叢集索引)
確定適合的修複方法
從上面的結果,我們知道是需要修複一個非叢集索引,由於叢集索引或堆沒有損壞,所以最簡單的方法是刪除再重新它。不過在這裡,我們也試一下重建索引(rebuild index)和建立索引時使用Drop_Existing選項是否可以呢?
首先,我們通過下面的SQL得到表名和索引名:
Select Object_Name(object_id) As TableName, name As IndexNameFrom sys.indexesWhere object_id = 341576255and index_id = 2
然後試試Rebuild index
-- Rebuild the index??Alter Index IX_FactResellerSales_CurrencyKey On dbo.FactResellerSales Rebuild;
結果:
The statement has been terminated.Msg 824, Level 24, State 2, Line 2SQL Server detected a logical consistency-based I/O error: incorrect pageid (expected 1:7171; actual 0:0). It occurred during a read of page (1:7171) in database ID 5 at offset 0x00000003806000 in file 'D:\SQL2012\Data\AdventureWorksDW2008R2_Data.mdf'. Additional messages in the SQL Server error log or system event log may provide more detail. This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.
再試建立索引時用Drop_Existing,結果得到同樣的結果:
最後我們用刪除再重新建立,修複成功:
我們再次運行DBCC CHECKDB,已經沒有錯誤了: