解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)
http://improve.dk/corrupting-databases-purpose-using-orcamdf-corruptor/
有时候你必须先作恶,后行善。情况就是 当你想磨练你的数据库修复技能
我现在添加了一个Corruptor 类到OrcaMDF里面 去测试新的RawDatabase 的功能。Corruptor 就跟他的名字一样--他会故意损坏数据库文件
Corruptor 本身是比较简单的。Corruptor 会随机选择一些页面并且简单的使用0来完全复写页面。
根据页面的类型,这可能会造成致命伤害
我不想多说什么了,不过万一。。。请不要在你的生产库上运行。这会损坏你的数据。
例子
有两个 Corruptor.CorruptFile重载方法,他们都返回integers 的枚举值 -- 一系列的pageid 列表并且被复写0的
下面的代码会损坏5%的页面在AdventureWorks2008R2LT.mdf 文件里面,然后他会输出每个被损坏了的页面ID 。
你可以定义损坏页面的百分比 只需要改变第二个参数
var
corruptedPageIDs = Corruptor.CorruptFile(
@"
C:\AdventureWorks2008R2LT.mdf
"
,
0.05
);
Console.WriteLine(
string
.Join(
"
,
"
, corruptedPageIDs));
606
,
516
,
603
,
521
,
613
,
621
,
118
,
47
,
173
,
579
,
323
,
217
,
358
,
515
,
615
,
271
,
176
,
596
,
417
,
379
,
269
,
409
,
558
,
103
,
8
,
636
,
200
,
361
,
60
,
486
,
366
,
99
,
87
为了使损坏更厉害,你也可以使用第二个重载方法,他允许你定义一个确切的损坏页面的数目,在一个确定的pageid范围内。
下面的代码会确切的损坏pageid在0到49这个范围内的10个页面,因此会损坏大部分的元数据,大家知道系统表的数据基本都存储在数据库最靠前的页面上
var
corruptedPageIDs = Corruptor.CorruptFile(
@"
C:\AdventureWorks2008R2LT.mdf
"
,
10
,
0
,
49
);
Console.WriteLine(
string
.Join(
"
,
"
, corruptedPageIDs));
16
,
4
,
0
,
32
,
15
,
14
,
30
,
2
,
49
,
9
在上面的情况我非常不幸的看到 下面这些页面都被填充了0 包括:
file header page,page 2 is the first GAM page,page 9 is the boot page ,page 16 allocation unit metadata。
这样的损坏程度,即使使用DBCC CHECKDB也没办法修复,留下给你的选择只有从备份中还原
或者,你可以尝试一下使用 OrcaMDF RawDatabase 去恢复尽可能多的数据,先到这里了,我以后还会继续介绍。
DBCC
TRACEON(
3604
,
-
1
)
GO
DBCC
PAGE(
[
sss
]
,
1
,
16
,
3
)
GO
DBCC
执行完毕。如果
DBCC
输出了错误信息,请与系统管理员联系。
PAGE: (
1
:
16
)
BUFFER:
BUF
@0x0000000080FDEB80
bpage
=
0x0000000080A74000
bhash
=
0x0000000000000000
bpageno
=
(
1
:
16
)
bdbid
=
8
breferences
=
0
bcputicks
=
0
bsampleCount
=
0
bUse1
=
19980
bstat
=
0xc00009
blog
=
0x32159
bnext
=
0x0000000000000000
PAGE HEADER:
Page
@0x0000000080A74000
m_pageId
=
(
1
:
16
) m_headerVersion
=
1
m_type
=
1
m_typeFlagBits
=
0x4
m_level
=
0
m_flagBits
=
0x200
m_objId (AllocUnitId.idObj)
=
7
m_indexId (AllocUnitId.idInd)
=
0
Metadata: AllocUnitId
=
458752
Metadata: PartitionId
=
458752
Metadata: IndexId
=
1
Metadata: ObjectId
=
7
m_prevPage
=
(
0
:
0
) m_nextPage
=
(
1
:
130
) pminlen
=
73
m_slotCnt
=
49
m_freeCnt
=
4225
m_freeData
=
4331
m_reservedCnt
=
0
m_lsn
=
(
1037
:
459
:
3
) m_xactReserved
=
0
m_xdesId
=
(
0
:
455
) m_ghostRecCnt
=
0
m_tornBits
=
-
563242027
Allocation Status
GAM (
1
:
2
)
=
ALLOCATED SGAM (
1
:
3
)
=
NOT
ALLOCATED
PFS (
1
:
1
)
=
0x60
MIXED_EXT ALLOCATED 0_PCT_FULL DIFF (
1
:
6
)
=
CHANGED
ML (
1
:
7
)
=
NOT
MIN_LOGGED
Slot
0
Offset
0x60
Length
77
Record Type
=
PRIMARY_RECORD Record Attributes
=
NULL_BITMAP Record Size
=
77
Memory
Dump
@0x000000000DC7A060
0000000000000000
:
10004900
00000300
00000000
01000003
†..I.............
0000000000000010
:
00000000
00000000
0001001f
00000001
†................
0000000000000020
:
00570000
00010056
00000001
000b0000 †.W.....V........
0000000000000030
:
00000000
00090000
00000000
00110000
†..... ..........
0000000000000040
:
00000000
00010000
000c0000
00
††††††††.............
Slot
0
Column
1
Offset
0x4
Length
8
Length (physical)
8
auid
=
196608
Slot
0
Column
2
Offset
0xc
Length
1
Length (physical)
1
type
=
1
Slot
0
Column
3
Offset
0xd
Length
8
Length (physical)
8
ownerid
=
196608
Slot
0
Column
4
Offset
0x15
Length
4
Length (physical)
4
status
=
0
Slot
0
Column
5
Offset
0x19
Length
2
Length (physical)
2
fgid
=
1
pgfirst
=
[
Binary data
]
Slot
0
Column
6
Offset
0x1b
Length
6
Length (physical)
6
pgfirst
=
0x1f0000000100
pgroot
=
[
Binary data
]
Slot
0
Column
7
Offset
0x21
Length
6
Length (physical)
6
pgroot
=
0x570000000100
pgfirstiam
=
[
Binary data
]
Slot
0
Column
8
Offset
0x27
Length
6
Length (physical)
6
pgfirstiam
=
0x560000000100
Slot
0
Column
9
Offset
0x2d
Length
8
Length (physical)
8
pcused
=
11
Slot
0
Column
10
Offset
0x35
Length
8
Length (physical)
8
pcdata
=
9
Slot
0
Column
11
Offset
0x3d
Length
8
Length (physical)
8
pcreserved
=
17
Slot
0
Column
12
Offset
0x45
Length
4
Length (physical)
4
dbfragid
=
1
Slot
0
Offset
0x0
Length
0
Length (physical)
0
KeyHashValue
=
(016862d84319)
SELECT COUNT(*) FROM sys.[allocation_units]
--131
SELECT * FROM sys.[allocation_units]
SELECT * FROM sys.[system_internals_allocation_units]
存储在数据库1:16页面上(是[sys.system_internals_allocation_units]系统表)《深入解析sql2008》
第十七篇完

