筆者單位的一臺Web服務器近來數據存儲出現異常,因為后臺采用的是SQL Server數據庫,之前對其進行過備份,因此決定對數據庫進行恢復。
本來數據恢復是簡單的事情,運行“RESTORE DATABASE DBNAME FROM='f:databakXXX.bak '”命令,就可以使用備份文件恢復數據庫(“DBNAME”表示目標數據庫名稱,“xxx.bak”表示備份文件的名稱),但是,在恢復時系統(tǒng)提 示“RESTORE cound not start database 'DBNAME' ,file ' DBNAME_log'on file 1”,“RESTORE DATABASE is terminating abnormally”,“SQL SERVER detected a logical consistency-Based I/Oerror:incorrect checksum”等警告信息,說明備份文件出現損壞,無法順利恢復數據。
該SQL Server數據庫最近只進行了一次備份,如果不能從該受損的備份文件中恢復數據,無疑會對Web服務器的運行造成不利影響。我們知道,當SQL Server在進行數據備份時,只是簡單地將數據頁面復制下來,一般不會做數據一致性檢查,當進行數據恢復時,則需要將數據庫恢復到事務一致的某個時間點,如果備份文件中的損壞部分對Redo前滾和Undo后滾造成影響,那么數據恢復就會出現問題。
既然在恢復備份文件時出現故障,那么忽略該錯誤,讓恢復操作繼續(xù)進行,或許可以完成恢復操作,至少可以得到盡可能多的有效數據。這里使用的是SQL Server 2012,針對這一故障,可以使用其提供的忽略錯誤功能,來嘗試解決上述故障。
在“RESTORE”命令中提供了名為“CONTINUE_AFTER_ERROR”的參數,可以讓恢復操作避開錯誤提示,嘗試修復報告中的所有錯誤,盡可能地還原備份文件中所有內容。當數據還原完成后,可以使用后續(xù)的事務日志備份,來恢復數據庫。當在恢復日志時出現錯誤,SQL Server可以在日志中進行記錄,禁止用戶訪問這些和事務相關的頁面,讓數據庫可以盡可能地聯機運行。當然,這些修復行為不是萬能的,在某些情況下可能丟失部分數據。對于一般的數據來說,當出現錯誤時,會進入可疑狀態(tài),但不會影響到恢復的進程。
對于存在問題的頁面,會被記錄到相關的表和日志中。如果數據錯誤出現在備份文件的關鍵位置(例如文件頭等),那么恢復操作將徹底失敗,因此該方法無法保證解決所有的恢復失敗故障。當數據庫還原之后,還需要使用SQL Server提供的DBCC CHECKDB命令,來修復數據庫,讓其可以真正處于可用狀態(tài)。使用該命令,可以有效地檢測數據庫中是否存在損壞情況,當發(fā)現有損壞的跡象時,可以盡可能地修復數據庫,使用戶可以正常訪問其中的數據。
在執(zhí)行該命令時,會檢測一些關鍵的系統(tǒng)表,在每張數據表中都存在聚集索引,通過檢測,保證這些表中的所有頁面以及其中的數據可以正常讀出。該命令會檢查目標數據庫中所有頁面的分配情況,通過檢驗內部結構,來跟蹤這些頁面以及之間的關系。同時,檢測數據庫中的所有表是否正確鏈接索引,索引是否正常排序,所有指針是否一致,頁面上的數據是否合理,頁面偏移量是否正確,分區(qū)表或索引的每行是否處于正確的分區(qū)中。可以檢測數據據庫中的系統(tǒng)表中記錄的元數據的邏輯一致性,驗證數據庫中所有索引試圖的內容,檢測數據庫中的Service Broker數據等。
找到了修復的方法后,執(zhí) 行“RESTORE DATABASE DBNAMEFROM= 'f:databakXXX.bak ' WITH CONTINUE_AFTER_ERROR”命令,執(zhí)行恢復操作,系統(tǒng)提示“Restore was successful but defered transactions remain. These transactions cannot be resolved because there are data that is unavailable”,“RESTORE WITH CONTINUE_AFTER_ERROR was successful but some damage was encountered,Inconsi stencies in the database are possible”,“RESTORE DATABASE successfully processes x pages in x seconds”等提示,說明數據庫恢復順利完成。
之后該數據庫處于Suspect可疑狀態(tài)無法直接使用,執(zhí)行“ALTER CHECKDB DNNAME SET EMERGENCY”命令,將其設置為緊急狀態(tài)。執(zhí)行“DBCC CHECKDB(DBNAME)”,“DBCC CHECKED(DBNAME, REPAIR_ALLOW_DATA_LOSS)”命令進行修復處理。
修復完成后,執(zhí)行“use dbname”,“select * from salestb”等命令,可以正常打開并訪問其中的數據表。經過檢測,雖然丟失了少量數據,但是絕大部分數據都還在,這對數據庫影響不大,至此數據恢復成功完成。
當然,這里的緊急修復操作,只是無奈之舉,存在丟失數據甚至失敗的風險,因此在日常維護數據庫時,需要定期對數據庫進行備份和檢測,將風險降到最低。因為單位的SQL Server數據庫體積不大,所以執(zhí)行“DBCC CHECKDB”命令消耗的時間不長,但是對于體積龐大的數據庫來說,如果存在的問題較多的話,修復起來就會極為耗時,同時,還會引起數據庫阻塞。