先執行一下以下SQL語句,我的測試環境為SQL2005
dbcc traceon(3604)
go
dbcc page(master,1,0,2)
可以看到MDF文件的一些物理結構信息,其中包括重要的頭96個字節。也就是第一個頁面的文件頭。
........
PAGE HEADER:
Page @0x03FA0000
m_pageId = (1:0) m_headerVersion = 1 m_type = 15
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8
m_objId (AllocUnitId.idObj) = 99 m_indexId (AllocUnitId.idInd) = 0 Metadata: AllocUnitId = 6488064
Metadata: PartitionId = 0 Metadata: IndexId = 0 Metadata: ObjectId = 99
m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 0
m_slotCnt = 1 m_freeCnt = 7937 m_freeData = 3059
m_reservedCnt = 0 m_lsn = (149:448:1) m_xactReserved = 0
m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = -1073741694
........
DATA:
Memory Dump @0x62FEC000
62FEC000: 010f0000 08000000 00000000 00000000 †................
62FEC010: 00000000 00000100 63000000 011ff30b †........c.......
62FEC020: 00000000 01000000 95000000 c0010000 †................
62FEC030: 01000000 00000000 00000000 820000c0 †................
62FEC040: 00000000 00000000 00000000 00000000 †................
62FEC050: 00000000 00000000 00000000 00000000 †................
以上藍色的文字就是文件頭的一些信息。如果這些信息損壞將會造成嚴重的後果。
經過簡單的逐個字節分析,中間借助了windows計算器和c#的BitConverter.GetBytes函數。得出了如下文件結構圖,其中每行4個字節,一共分析了文件頭的前64個字節。
00:0F m_headerVersion m_type m_typeFlagBits m_level m_flagBits m_indexId m_prevPage(2) m_prevPage(1) pminlen 10:1F m_nextPage(2) m_nextPage(1) m_slotCnt AllocUnitId.idObj m_freeCnt m_freeData 20:2F m_pageId(2) m_pageId(1) m_reservedCnt m_lsn(1) m_lsn(2) 30:3F m_lsn(3) m_xactReserved m_xdesId(2) m_xdesId(1) m_ghostRecCnt m_tornBits
在數據庫的頭96個字節中第0x40開始直道0x5F應該都是0。
我發現只有測試頁的m_pageId 的冒號前面的數字不為1時才在0x40到0x5f寫入數據。但是具體代表什麼還沒有看出來。
姑且認為數據庫第一個頁面的0x00-0x3f就如上圖所示,0x40-0x5f都為0(不正確的話請糾正一下)
這張圖有什麼用呢,如果你理解了上述參數的意義,用二進制編輯器打開一個頭文件損壞的mdf文件就有可能恢復這個已經損壞的數據庫。
偶不是dba也不是專業恢復數據的,只是個普通的開發人員,怎麼恢復還請有經驗人士補充一下。
有情提醒,這些東西非常危險,請不要隨意測試,最好找一個沒用的數據庫來研究。