SQL Server 2000在很多企業、電子商務網站的信息化平臺得到了普遍的應用??稍谌粘_\行中,因種種原因會造成SQL Server 2000運行出現故障,輕則出現“置疑”,重則數據庫系統崩潰。本文以圖示的方式,闡述某個大學的一次數據庫數據恢復過程。 本文恢復數據使用PC環境如下: 1)Windows 2000 Server(簡體中文)+SP4 2)Microsoft SQL Server 2000企業版(簡體中文)+SP3a
故障現象 1)游泳館收費系統連接不上SQL Server 2000數據庫。 2)啟動SQL Server服務失敗。 3)打開企業管理器,啟動服務也是失?。床坏綌祿鞓淠夸洠?。 要命的是當技術員發現問題,已經卸載SQL Server 2000后重新安裝過了,想利用master數據庫是不可能了。更要命的是,居然沒有2005年的備份數據庫,只有2004年6月的數據庫備份文件。 第一招:附加數據庫 拷貝SQL Server 2000數據文件zytk.mdf到d:recovery下。在企業管理器中,右鍵數據庫,選擇所有任務→附加數據庫。單擊瀏覽("...")按鈕選擇要附加的數據庫mdf文件d:recoveryzytk.mdf,發現日志文件是錯誤的(如圖1)。 此時拷貝zytk.ldf到d:recovery目錄下,再進行上述步驟,日志文件仍是錯誤(就是那個可惡的紅叉叉)。單擊確定按鈕,提示日志文件錯誤(如圖2和圖3)。 發現提示的日志文件路徑是D:Microsoft sql servermssql data zytk_log.ldf。于是在D盤建立D:Microsoft sql servermssqldata目錄,并將zytk.mdf拷貝這個目錄下。繼續嘗試上述附加數據庫步驟,日志文件的路徑已經變化,仍舊沒能附加數據庫成功(錯誤1813)(如圖4與圖1相比)。 在查詢分析器中執行SQL腳本 use master EXEC sp_attach_db "ZYTK", "D:Microsoft sql servermssqldataZYTK.mdf","D:Microsoft sql servermssqldataZYTK_log.ldf" 查詢分析器提示: 服務器:消息5105,級別16,狀態4,行1 設備激活錯誤。物理文件名 'D:Microsoft sql servermssql dataZYTK_log.ldf' 可能有誤。 將D:recovery目錄下zytk.mdf改名zytk-old.mdf。在企業管理器中新建數據庫zytk,選擇數據庫文件路徑為D:recoveryZYTK_Data.MDF,日志文件路徑為D:recoveryZYTK_ log.LDF。在企業管理器中,右鍵停止,以便停止SQL Server服務。待SQL Server服務停止后將D:recoveryzytk.mdf改名zytk_data-new.mdf,同時將zytk-old.mdf改名為zytk_data.mdf,在企業管理器中啟動SQL Server服務。數據庫ZYTK將會置疑。 Use master select * from SysDatabases where name='ZYTK' 看到數據庫的status=1073741840,下面我們的目標是要將這個值修改到32768(緊急模式)再到16(假正常模式,這是我在這個故障處理中的叫法)。 缺省情況下,SQL Server不允許修改status值。直接作update,系統提示服務器: 消息 259,級別 16,狀態 2,行 1未啟用對系統目錄的特殊更新。系統管理員必須重新配置 SQL Server 以允許這種操作。 所以先執行SQL腳本,讓SQL Server允許我們修改status值: sp_configure 'allow updates', 1 RECONFIGURE WITH OVERRIDE 修改status到32768(緊急模式),執行SQL腳本: update SysDatabases set status=32768 where name='zytk' 在查詢分析器中執行SQL腳本,檢查數據庫完整性。 dbcc checkdb ('ZYTK') with ALL_ERRORMSGS 執行結果有很多錯誤(具體執行結果見03CheckDB-ZYTK結果.txt),跟筆者估計一致,數據庫的索引出了大問題。下面摘錄其中一個錯誤: 對象 'cw_Check_Detail' 有 0 行,這些行位于 0 頁中。 服務器: 消息 8936,級別 16,狀態 1,行 1 表錯誤: 對象 ID 181575685,索引 ID 1。B 樹鏈的鏈接不匹配。(1:4987)->next = (1:2601),但 (1:2601)->Prev = (1:4947)。 在查詢分析器中執行SQL腳本,將數據庫ZYTK的status修改為16: update SysDatabases set status=16 where name='zytk' 刷新數據庫,ZYTK(緊急模式)轉變為ZYTK。注意此時不能重新啟動SQL Server服務!否則數據庫ZYTK的狀態還會變成置疑。這時,數據庫處理算是成功一半!這個假正常模式(我的叫法)還是不能做數據庫備份的。否則會提示如圖5的錯誤。 不過這時可以看到那些可恨又可愛的表及表中的數據了。 在d:recovery下建立目錄BCP,再在d:recoveryBCP下建立error目錄。利用SQL Server數據庫的SysObjects表可以生成批量的BCP命令: 從數據庫中各表導出所有表的數據: Use %1 Select 'BCP %1..' + name + ' out d:recoveryBCP' +name + '.txt -c -S%2 -U%3 -P%4 >D:recoveryBCPerror out_'+name+'.txt' from sysobjects where type = 'U' order by name 從數據文件導回到數據庫中的各表: Use %1 Select 'BCP %1..' + name + ' in d:recoveryBCP' +name + '.txt -c -S%2 -U%3 -P%4 >D:recoveryBCPerrorin_'+name+'.txt' from sysobjects where type = 'U' order by name 注意:type = "U",U必須大寫,表用戶自定義表。-S服務器,-P密碼,%1為數據庫,%2為本機SQL Server實例名,一般就是計算機名,%3為登錄賬戶,一般為sa,%4為登錄密碼。 本文中具體的例子如下: Select 'BCP ZYTK..' + name + ' out d:recoveryBCP' +name + '.txt -c -Stech -Usa -P123456 >d: recoveryBCPerrorout_'+name+'.txt' from sysobjects where type = 'U' order by name 將上述SQL腳本的查詢結果全選后另存為批處理文件zytk.bat。用于從數據庫ZYTK中各表導出以表名命名的txt文件: Select 'BCP ZYTK015..' + name + ' in d:recoveryBCP' +name + '.txt -c -Stech -Usa -P123456 >d: recoveryBCPerrorin _'+name+'.txt' from sysobjects where type = 'U' order by name 將上述SQL腳本的查詢結果全選后另存為批處理文件zytk015.bat。用于將上述各表的txt文件導回到數據庫ZYTK015。執行zytk.bat,執行完畢后要檢查D:recoveryBCPerror下的每個out_表名.txt文件(見Error_outFiles.rar),查看是否有誤。當然導入后要檢查in表名.txt文件,查看是否有誤。這是必須的,筆者因想偷懶,結果因導入數據不完整而重新恢復多花了半天,教訓??!我處理的數據庫表一共有166個,為了提高恢復準確性,最好能找個人一起幫助看著過程是否有誤。 新建ZYTK015要保證跟ZYTK一樣的表結構(如主鍵、索引等,本文不再贅述,本文是從ZYTK中生成SQL腳本,然后新建數據庫(下轉第71頁)(上接第70頁)ZYTK015后執行創建表、主鍵、索引腳本。當然一般還有視圖、存儲過程等加密過的,是不能導出為SQL腳本,那得想其它的辦法,本文是還原2004年的數據庫來實現的)。 執行zytk015.bat,執行完畢后要檢查D:recoveryBCPerror每個in_表名.txt文件(見Error_inFiles.rar)。筆者遇到一個歷史流水表導入失敗,后來經過分時間段導入,多次試驗才得以成功?;謴偷臅r候一定要細心,并且記錄關鍵步驟的操作內容,否則做到哪一步,自己都暈菜了,更不用說成功地恢復數據庫了!如果在zytk015數據庫中能看到數據,那就是大功告成了。不過不要得意哦,還得運行游泳收費系統來測試數據的正確性。測試之前記得要備份數據庫哦。 最后,有個問題要說明一下:如果表間有關聯,使用BCP恢復起來就麻煩一點。一般的做法可以把外鍵之類的表間關系去掉,等導入數據后在用SQL腳本重新創建這些關系。這個做法數據的有效性得由我們自己去判斷了,如果有問題還得手工修改(一般需要開發人員協助,因為只有他們才能去查代碼)。
同時也詳細闡述了BCP實用工具的詳細用法,希望這個處理過程和處理方法能對大家有所啟示。
恢復嘗試
第二招:用T-SQL附加數據庫
在查詢分析器中執行SQL腳本: