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 輸出了錯誤信息,請與系統管理員聯系。
1 -------------------------------------頁面號912--------------------------------------------------------------------- 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_id 5 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)導出數據
但是,除非你的完全備份沒有數據庫錯誤,不然無論你選擇哪種方案都意味着部分數據丟失,至於丟失哪部分數據,誰也不知道,只有在下次查詢到
丟失的數據的時候報錯才知道!!!
最后,因為他沒有完全備份,所以他最終選擇了導出數據
總結:一句話“大家以后一定要做好數據庫的備份工作”
繼續干活了,祝大家新的一個星期愉快!!o(∩_∩)o 哈哈