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