【SQL Server备份恢复】数据库恢复:对page header的恢复
前兩天在論壇,看到有個網友提問,說是:
格式化磁盤前把.mdf和.ldf拷貝出來了,然后格式化完成后在拷貝回去(拷貝前后都沒有錯誤提示,文件大小也一樣),在企業管理器中附加數據庫出錯,提示“錯誤823”,附加數據庫失敗。從網上搜了搜方案:重建同名數據庫之類的做法都試過了,都不能解決問題。請問版主或各位高手,有什么解決方案嗎?
注:拷貝之前數據庫使用正常,并且以前都是此種方法附加的,這次不知如何出現這樣的問題了。
幫他嘗試恢復:
1、他已經按照網上的方法,新建了一個同名的數據庫。
2、停止服務,然后把原始的文件拷貝到目錄中。
3、啟動服務,發現數據庫處于質疑狀態。
4、運行如下命令,都報錯:打不開數據庫
dbcc checkdb(xxx); dbcc checkdb(xxx,repair_allow_data_loss);5、運行如下命令成功,?設置數據庫為緊急模式 ?
Use Master GO sp_configure 'allow updates', 1 reconfigure with override GO UPDATE sysdatabases SET status = 32768 where name = 'xxx' GO
6、再次運行命令,報錯:數據庫必須處于單用戶模式
dbcc checkdb(xxx,repair_allow_data_loss);
7、如果如下命令,設置數據庫為單用戶模式:
alter database test set single_user
8、再次運行命令,還是報錯:數據庫必須處于單用戶模式
dbcc checkdb(xxx,repair_allow_data_loss);
在這里就覺得很奇怪,明明已經設置為單用戶模式了,怎么還報這個錯誤呢?
在網上找了一下,發現有很多人都有這個問題,但是沒有解決辦法。
9、嘗試運行如下命令,但類似這樣的報錯:
服務器: 消息 8909,級別 16,狀態 1,行 1 表錯誤: 對象 ID 0,索引 ID 0,頁 ID 0。 服務器: 消息 8966,級別 16,狀態 1,行 1 未能讀取并閂鎖頁 (1:123456)(用閂鎖類型 SH)。sysobjects 失敗。
在網上找到一篇文章:
sql server 系統表損壞修復方法?http://wenku.baidu.com/view/901cd511f18583d04964592e
這個文章中提到的解決方法就是,新建一個數據庫,通過dts,把原來數據庫的數據,導出到新的數據庫中,但前提是其中的表都能訪問,也就是能夠select * from 表,否則就沒用了。
那么有沒有什么好的辦法,能修復呢?
在網上找了一下,發現有專業的數據恢復公司,能恢復這種錯誤,從文章中提到的信息來看,應該通過直接構造損壞的頁面來修復的。
由于這種情況比較難重現,所以這里模擬當某個數據頁的page header損壞時,如何手動修復這個數據頁,其實就是一個復制粘帖的過程。
1、先創建一個數據庫,創建表,插入數據:
create database w go use w go if OBJECT_ID('test') is not null drop table test select * into test from sys.objects go insert into test select * from test
2、分離數據庫w,把數據文件和日志文件,直接復制到一個備份目錄。
3、本來通過dbcc writelog來修改數據,但是應該是沒有修改好。
dbcc writepage的語法為: dbcc writepage ({ dbid,'dbname' }, fileid, pageid, offset, length, data) --生成96個字節的數據 select '0x'+replicate('00',96) dbcc writepage('w',1,310,0,96, 0x000000000000000000000000000000000000000 00000000000000000000000000000000000000000 00000000000000000000000000000000000000000 00000000000000000000000000000000000000000 000000000000000000000000000000) /* 消息 8939,級別 16,狀態 5,第 1 行 表錯誤: 對象 ID 0,索引 ID -1,分區 ID 0,分配單元 ID 0 (類型為 Unknown),頁 (0:0)。測試(m_headerVersion == HEADER_7_0)失敗。值為 0 和 1。 消息 8939,級別 16,狀態 6,第 1 行 表錯誤: 對象 ID 0,索引 ID -1,分區 ID 0,分配單元 ID 0 (類型為 Unknown),頁 (0:0)。測試((m_type >= DATA_PAGE && m_type <= UNDOFILE_HEADER_PAGE) || (m_type == UNKNOWN_PAGE && level == BASIC_HEADER))失敗。值為 0 和 0。 消息 8939,級別 16,狀態 7,第 1 行 表錯誤: 對象 ID 0,索引 ID -1,分區 ID 0,分配單元 ID 0 (類型為 Unknown),頁 (0:0)。測試(m_freeData >= PageHeaderOverhead () && m_freeData <= (UINT)PAGESIZE - m_slotCnt * sizeof (Slot))失敗。值為 0 和 8192。 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。 */
所以,改用二進制編輯工具,輸入:0x0026C000,定位到這個物理偏移,然后修改了數據庫w中的fileID為1,pageID為310的,前96個字節全為00,這個正好是page header部分:
select 8*1024*310 as '310頁在文件中的物理偏移', CAST(8*1024*310 as varbinary) '轉化為16進制' /* 310頁在文件中的物理偏移 轉化為16進制 2539520 0x0026C000 */
4、重新附加這個數據庫
dbcc checkdb(w) /* 消息 8909,級別 16,狀態 1,第 1 行 表錯誤: 對象 ID 0,索引 ID -1,分區 ID 0,分配單元 ID 0 (類型為 Unknown),頁 ID (1:310) 在其頁頭中包含錯誤的頁 ID。頁頭中的 PageId = (0:0)。 CHECKDB 發現有 0 個分配錯誤和 1 個一致性錯誤與任何單個的對象都沒有關聯。 消息 8928,級別 16,狀態 1,第 1 行 對象 ID 981578535,索引 ID 0,分區 ID 72057594038910976,分配單元 ID 72057594042580992 (類型為 In-row data): 無法處理頁 (1:310)。有關詳細信息,請參閱其他錯誤消息。 CHECKDB 在數據庫 'w' 中發現 0 個分配錯誤和 2 個一致性錯誤。 對于由 DBCC CHECKDB (w)發現的錯誤,repair_allow_data_loss 是最低的修復級別。 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。 */
5、把數據庫分離,從備份的文件中,復制page header到這個文件
6、再次附加數據庫,就可以查詢了。
不過,使用repair_allow_data_loss也可以恢復。
轉載于:https://blog.51cto.com/yupeigu/1367935
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【SQL Server备份恢复】数据库恢复:对page header的恢复的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线性表--链式实现方式
- 下一篇: [UML]UML系列——用例图Use C