SQLSERVER页面错误的解决方案记录
前天帮人解决一个问题,他的SQLSERVER出现了页面错误,使用dbcc checkdb修复没有报错,但是收缩数据库的时候报错说“有页面错误”
今天记录一下我帮他解决的方法
先声明一下我是使用自己的数据库来做演示的,本人自己的数据库没有任务数据库错误,我只是拿自己的数据库作为例子
朋友的SQLSERVER出现如下错误:
消息 824,级别 24,状态 2,第 1 行
SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确(应为 9:912,但实际为 0:0)。在文件 'I:\data\PIMRpt_DB12_f.ndf' 中、偏移量为 0x00000000720000 的位置对数据库 ID 5 中的页 (9:912) 执行 读取 期间,发生了该错误。SQL Server 错误日志或系统事件日志中的其他消息可能提供了更详细信息。这是一个威胁数据库完整性的严重错误条件,必须立即纠正。请执行完整的数据库一致性检查(DBCC CHECKDB)。此错误可以由许多因素导致;有关详细信息,请参阅 SQL Server 联机丛书。
824错误是典型错误
上面的错误信息表示页面号912有错误页 (9:912)
说明一下:我自己本机演示的数据库使用我自己本机上的pratice数据库,稍后我会使用DBCC PAGE显示出索引页跟数据页的不同
下面说一下解决步骤:
步骤一:找出页所属objectid 和页面信息
使用”DBCC PAGE(dbid,fileid,pageid,formatid) --formatid一般为3“ (formatid的可选值为1,2,3 一般3是比较友好的其余两种显示格式比较深奥)
语句来找出错的那个页面的信息
1 EXEC sys.sp_helpdb @dbname = pratice --找出数据库ID
2
3 USE pratice
4 5 EXEC sys.sp_helpfile --找出数据文件ID
然后就可以运行下面语句了:
下面这两句要一起运行
1 DBCC TRACEON(3604,-1)2 3 DBCC PAGE(13,1,10,3) --指定错误页面号10
--下面我是分别查看了10号页面和912号页面 10号页面是索引页面,912号页面是数据页面
再说明一下indexid的值
IndexId=0 堆 数据页
IndexId=1 聚集索引 索引页
IndexId>1 非聚集索引 索引页
由于时间关系我直接输出了,里面有解析
1 --------------------------页面号10--------------------------------------------------------------------2 --输出结果 页面号为10的
3 --根据显示结果中的IndexId=1表示这个页面存储的是索引
4 --Metadata: IndexId = 1
5 --Metadata: ObjectId = 44
6 --m_pageId = (1:10)
7 --Metadata: PartitionId = 281474979594240
8
9
10 --DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
11
12 --PAGE: (1:10)
13 --
14 --
15 --BUFFER:
16 --
17 --
18 --BUF @0x03EDB51C
19 --
20 --bpage = 0x074C6000 bhash = 0x00000000 bpageno = (1:10)
21 --bdbid = 13 breferences = 0 bUse1 = 35725
22 --bstat = 0x2c00009 blog = 0x32159 bnext = 0x00000000
23 --
24 --PAGE HEADER:
25 --
26 --
27 --Page @0x074C6000
28 --
29 --m_pageId = (1:10) m_headerVersion = 1 m_type = 10
30 --m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x200
31 --m_objId (AllocUnitId.idObj) = 44 m_indexId (AllocUnitId.idInd) = 1 Metadata: AllocUnitId = 281474979594240
32 --Metadata: PartitionId = 281474979594240 Metadata: IndexId = 1
33 --Metadata: ObjectId = 44 m_prevPage = (0:0) m_nextPage = (0:0)
34 --pminlen = 90 m_slotCnt = 2 m_freeCnt = 6
35 --m_freeData = 8182 m_reservedCnt = 0 m_lsn = (12:176:14)
36 --m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
37 --m_tornBits = -1951658170
38 --
39 --Allocation Status
40 --
41 --GAM (1:2) = ALLOCATED SGAM (1:3) = NOT ALLOCATED
42 --PFS (1:1) = 0x70 IAM_PG MIXED_EXT ALLOCATED 0_PCT_FULL DIFF (1:6) = CHANGED
43 --ML (1:7) = NOT MIN_LOGGED
44 --
45 --IAM: Header @0x5E7FC064 Slot 0, Offset 96
46 --
47 --sequenceNumber = 0 status = 0x0 objectId = 0
48 --indexId = 0 page_count = 0 start_pg = (1:0)
49 --
50 --
51 --IAM: Single Page Allocations @0x5E7FC08E
52 --
53 --Slot 0 = (0:0) Slot 1 = (1:50) Slot 2 = (0:0)
54 --Slot 3 = (0:0) Slot 4 = (0:0) Slot 5 = (0:0)
55 --Slot 6 = (0:0) Slot 7 = (0:0)
56 --
57 --
58 --IAM: Extent Alloc Status Slot 1 @0x5E7FC0C2
59 --
60 --(1:0) - (1:43256) = NOT ALLOCATED
61 --
62 --
63 --DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
2 --因为SQLSERVER输出有4000多行,所以我只摘录了一部分
3
4 --输出结果 页面号为912的
5 --根据显示结果中的IndexId=0表示这个页面是数据页
6 --d = 超级坏 是表里面的数据
7 --Metadata: IndexId = 0
8 --Metadata: ObjectId = 197575742
9 --Metadata: PartitionId = 72057594039500800 --页面所属分区
10 --m_pageId = (1:912)
11
12
13 --DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
14 --
15 --PAGE: (1:912)
16 --
17 --
18 --BUFFER:
19 --
20 --
21 --BUF @0x03F3E79C
22 --
23 --bpage = 0x0A20A000 bhash = 0x00000000 bpageno = (1:912)
24 --bdbid = 13 breferences = 3 bUse1 = 35858
25 --bstat = 0xc00009 blog = 0x21212159 bnext = 0x00000000
26 --
27 --PAGE HEADER:
28 --
29 --
30 --Page @0x0A20A000
31 --
32 --m_pageId = (1:912) m_headerVersion = 1 m_type = 1
33 --m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0x200
34 --m_objId (AllocUnitId.idObj) = 89 m_indexId (AllocUnitId.idInd) = 256
35 --Metadata: AllocUnitId = 72057594043760640
36 --Metadata: PartitionId = 72057594039500800 Metadata: IndexId = 0
37 --Metadata: ObjectId = 197575742 m_prevPage = (1:911) m_nextPage = (1:913)
38 --pminlen = 25 m_slotCnt = 155 m_freeCnt = 7
39 --m_freeData = 7875 m_reservedCnt = 7 m_lsn = (2252:12136:46)
40 --m_xactReserved = 7 m_xdesId = (0:2442865) m_ghostRecCnt = 0
41 --m_tornBits = 437279274
42 --
43 --Allocation Status
44 --
45 --GAM (1:2) = ALLOCATED SGAM (1:3) = NOT ALLOCATED PFS (1:1) = 0x44 ALLOCATED 100_PCT_FULL
46 --DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED
47 --
48 --Slot 0 Offset 0x60 Length 65
49 --
50 --Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
51 --
52 --Memory Dump @0x5F49C060
53 --
54 --00000000: 30002200 50d65f01 339f0000 64b90100 †0.".P._.3...d...
55 --00000010: 016cb901 00000000 004f57ba 4e00042d †.l.......OW.N..-
56 --00000020: 00000800 40040033 0039003d 00410063 †....@..3.9.=.A.c
57 --00000030: b9010085 8da77e4f 57bbb5c8 cb4f57ba †......~OW....OW.
58 --00000040: 4e†††††††††††††††††††††††††††††††††††N
59 --
60 --Slot 0 Column 0 Offset 0x2f Length 4
61 --
62 --DROPPED = 112995
63 --
64 --Slot 0 Column 1 Offset 0x4 Length 8
65 --
66 --c = 08 2 2011 9:21PM
67 --
68 --Slot 0 Column 2 Offset 0x33 Length 6
69 --
70 --d = 超级坏
71 --
72 --Slot 0 Column 3 Offset 0xc Length 4
73 --
74 --a = 112996
75 --
76 --Slot 0 Column 4 Offset 0x39 Length 4
77 --
78 --DROPPED = 坏人
79 --
80 --Slot 0 Column 5 Offset 0x10 Length 9
81 --
82 --e = 113004
83 --salary = [NULL]
84 --
85 --Slot 0 Column 7 Offset 0x3d Length 4
86 --
87 --b = 坏人
88 --
89 --Slot 1 Offset 0xa1 Length 65
90 --
91 --Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
92 --
93 --Memory Dump @0x5F49C0A1
94 --
95 --00000000: 30002200 50d65f01 339f0000 65b90100 †0.".P._.3...e...
96 --00000010: 016db901 00000000 004f57ba 4e00042d †.m.......OW.N..-
97 --00000020: 00000800 40040033 0039003d 00410064 †....@..3.9.=.A.d
98 --00000030: b9010085 8da77e4f 57bbb5c8 cb4f57ba †......~OW....OW.
99 --00000040: 4e†††††††††††††††††††††††††††††††††††N
100 --
101 --Slot 1 Column 0 Offset 0x2f Length 4
102 --
103 --DROPPED = 112996
104 --
105 --Slot 1 Column 1 Offset 0x4 Length 8
106 --
107 --c = 08 2 2011 9:21PM
108 --
109 --Slot 1 Column 2 Offset 0x33 Length 6
110 --
111 --d = 超级坏
112 --
113 --Slot 1 Column 3 Offset 0xc Length 4
114 --
115 --a = 112997
116 --
117 --Slot 1 Column 4 Offset 0x39 Length 4
118 --
119 --DROPPED = 坏人
120 --
121 --Slot 1 Column 5 Offset 0x10 Length 9
122 --
123 --e = 113005
124 --salary = [NULL]
125 --
126 --Slot 1 Column 7 Offset 0x3d Length 4
127 --
128 --b = 坏人
129 --
130 --Slot 2 Offset 0xe2 Length 9
131 --
132 --Record Type = FORWARDING_STUB Record Attributes =
133 --Memory Dump @0x5F49C0E2
134 --
135 --00000000: 04f12100 0001003f 00†††††††††††††††††..!....?.
136 --Forwarding to = file 1 page 8689 slot 63
137 --
138 --Slot 3 Offset 0xeb Length 65
139 --
140 --Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
141 --
142 --Memory Dump @0x5F49C0EB
143 --
144 --00000000: 30002200 50d65f01 339f0000 67b90100 †0.".P._.3...g...
145 --00000010: 016fb901 00000000 004f57ba 4e00042d †.o.......OW.N..-
146 --00000020: 00000800 40040033 0039003d 00410066 †....@..3.9.=.A.f
147 --00000030: b9010085 8da77e4f 57bbb5c8 cb4f57ba †......~OW....OW.
148 --00000040: 4e†††††††††††††††††††††††††††††††††††N
149 --
150 --Slot 3 Column 0 Offset 0x2f Length 4
151 --
152 --DROPPED = 112998
153 --
154 --Slot 3 Column 1 Offset 0x4 Length 8
155 --
156 --c = 08 2 2011 9:21PM
157 --
158 --Slot 3 Column 2 Offset 0x33 Length 6
159 --
160 --d = 超级坏
161 --
162 --Slot 3 Column 3 Offset 0xc Length 4
163 --
164 --a = 112999
165 --
166 --Slot 3 Column 4 Offset 0x39 Length 4
167 --
168 --DROPPED = 坏人
169 --
170 --Slot 3 Column 5 Offset 0x10 Length 9
171 --
172 --e = 113007
173 --salary = [NULL]
174 --
175 --Slot 3 Column 7 Offset 0x3d Length 4
176 --
177 --b = 坏人
178 --
179 --Slot 4 Offset 0x12c Length 65
180 --
181 --Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
182 --
183 --Memory Dump @0x5F49C12C
184 --
185 --DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
步骤二:运行TSQL语句查询页面信息
再次说明一下:我的数据库只是作为例子,本人自己的数据库没有任务数据库错误,我只是拿自己的数据库作为例子,所以下面的相应参数要替换为你自己的根据上面
DBCC PAGE的输出
根据objectid运行下面语句看看页面属于哪个对象
1 SELECT 2 s.name AS N'架构名',3 o.name AS N'表名'4 FROM sys.sysobjects o INNER JOIN sys.schemas s ON o.uid=s.schema_id5 WHERE o.id=44
如果页是索引页的话运行下面这句,不是索引页不用运行
1 SELECT 2 id AS objectid,3 indid AS N'索引id',4 name AS N'索引名'5 FROM sys.sysindexes WHERE id=44 AND indid=1
如果页是索引页的话运行下面这句,不是索引页不用运行 clst是我自己数据库里的索引
1 EXEC sys.sp_helpindex @objname = N'clst' -- nvarchar(776)
步骤三:当你运行以上TSQL语句查询出页面信息之后就可以选择解决方案了
-----------------------------------------------解决方案------------------------------------------------------------
根据页类型是索引页还是数据页
(1)索引页:可以先Drop索引,然后再创建就修复了,没有任何数据损失.
(2)数据页:数据页根据以下三种解决方案
1、还原完全备份
如果上一次的FULL BACKUP也存在这种一致性错误而你又没有及时发现,只能找上上一次的BACKUP了.
所以你的维护计划里一定要有DBCC CHECKDB检查.
2、导出数据 前提:你要知道损坏的数据页属于哪个表你才知道要导出哪个表的数据
1、新建文件组和数据文件,不用新建数据库,只需要在原来的数据库下新建文件组和数据文件
2、在新文件组里重建损坏的表,意思是说新建一个表,这个表属于新建的文件组,而且表结构要跟损坏的表一样,例如表A(id int,name varchar(50))
那么新建的表B的字段要跟原表A一样
CREATE TABLE B(id INT,NAME VARCHAR(50)) ON 新建的文件组
3、将原始表数据导入到新表中 即把表A的数据导入到表B
4、清空原始表
3、dbcc checkdb 选择dbcc checkdb的参数要慎重
REPAIR_ALLOW_DATA_LOSS参数:如果是金融公司的数据库就很危险了
我朋友的情况:他查询出页面的信息里是这样的:
--Metadata: IndexId = -1
--Metadata: ObjectId = 265898
--m_pageId = (1:25632)
--Metadata: PartitionId = 0
由于该页面没有了所属分区,索引信息也查不到,这个页面属于无主孤云,这个时候他dbcc checkdb的时候没有报错
那他只能选择两种解决方案:(1)还原完全备份 (2)导出数据
但是,除非你的完全备份没有数据库错误,不然无论你选择哪种方案都意味着部分数据丢失,至于丢失哪部分数据,谁也不知道,只有在下次查询到
丢失的数据的时候报错才知道!!!
最后,因为他没有完全备份,所以他最终选择了导出数据