SQL Serve系統(tǒng)表損壞的處理方法
近日遇到二套數(shù)據(jù)庫損壞的問題,特給大家分享一下.如何解決!
一、SQL SVR數(shù)據(jù)庫中三張重要的系統(tǒng)表
    sysobjects:在數(shù)據(jù)庫內(nèi)創(chuàng)建的每個對象(約束、默認值、日志、規(guī)則、存
            儲過程等)在表中占一行。
sysindexes:數(shù)據(jù)庫中的每個索引和表在表中各占一行。
syscolumns:每個表和視圖中的每列在表中占一行,存儲過程中的每個參數(shù)
            在表中也占一行。
這三張表用ID(表ID)字段關(guān)聯(lián)。這三張系統(tǒng)表一旦損壞,與之對應(yīng)數(shù)據(jù)庫對象將無法訪問,其作用相當于DOS中的“文件分配表” 。
二、系統(tǒng)表損壞的癥狀
u      用 DBCC CHECKDB 攜帶任何參數(shù)都無法修復(fù)數(shù)據(jù)庫,也就是說:DBCC CHECKDB對這個帳套根本不起作用;
u      無法執(zhí)行如下操作:
select * from sysobjects 或select * from sysindexes
或select * from syscolumns ;
u      無法用SQL server DTS或其他SQL 腳本導(dǎo)庫工具進行導(dǎo)庫,導(dǎo)庫的中途失敗,報告:連接中斷;
u      在企業(yè)管理器或查詢分析器中,部分用戶數(shù)據(jù)表無法訪問。
三、處理方法
四、例
例:一sql svr數(shù)據(jù)庫,實體名為:AIS20030529181217
用DBCC CHECKDB檢測,報告(用DBCC CHECKDB 帶任何參數(shù)都是以下提示):
服務(wù)器: 消息 8966,級別 16,狀態(tài) 1,行 1
未能讀取并閂鎖頁 (1:29262)(用閂鎖類型 SH)。SYSOBJECTS 失敗。
DBCC 執(zhí)行完畢。如果 DBCC 輸出了錯誤信息,請與系統(tǒng)管理員聯(lián)系。
執(zhí)行select * from sysobjects,報告如下:
服務(wù)器: 消息 644,級別 21,狀態(tài) 3,行 1
未能在索引頁 (1:29262) 中找到 RID ‘16243a6d19100’ 的索引條目(索引 ID 0,數(shù)據(jù)庫 ‘AIS20030529181217’)。
連接中斷
  但是執(zhí)行select * from sysindexes 和select * from syscolumns 正常。
  這說明只有sysobjects表損壞,而 sysindexes 和 syscolumns 沒有問題。
處理步驟:
第一步: 處理可以訪問的數(shù)據(jù)表
(1.1) 找出哪些表不可訪問;
  新建立一個sql svr數(shù)據(jù)庫,數(shù)據(jù)庫實體名為AisNew。進入查詢分析器,執(zhí)行如下SQL:
****************************************************
use AIS20030529181217
DECLARE @TbName VARCHAR(80)
DECLARE FindErrTable SCROLL CURSOR FOR 
  select name from AisNew.dbo. sysobjects where xtype=‘u’ order by name
OPEN FindErrTable
FETCH FindErrTable INTO  @TbName
  WHILE @@FETCH_STATUS<>-1
    BEGIN
          print  @TbName
          exec( ‘select top 1 * from’ +  @TbName)
          FETCH FindErrTable INTO  @TbName
    END
PRINT ‘Scan Complate…’
CLOSE FindErrTable
DEALLOCATE FindErrTable
****************************************************
  執(zhí)行此SQL給出的報告的最后幾行為:
…
T_voucher
服務(wù)器: 消息 644,級別 21,狀態(tài) 3,行 1
未能在索引頁 (1:29262) 中找到 RID ‘161dd201a100’ 的索引條目(索引 ID 0,數(shù)據(jù)庫 ‘AIS20030529181217’)。
連接中斷
    根據(jù)以上報告可以知道 T_voucher 表在sysobjects表中的對應(yīng)記錄出錯,造成T_voucher不能訪問。修改上面的SQL:在聲明游標的記錄集中屏蔽T_voucher 表。即:
…
DECLARE FindErrTable SCROLL CURSOR FOR 
select name from AisNew.dbo. sysobjects where xtype=‘u’ and name != ’t_voucher’
order by name
…
    修改完畢,繼續(xù)執(zhí)行此SQL。如此反復(fù),就能夠不斷報告出sysobjects中那些表不能訪問。
(1.2) 導(dǎo) 庫
      用SQL DTS工具將AIS20030529181217中可以訪問的數(shù)據(jù)表導(dǎo)入AisNew。
第二步:處理不可訪問的數(shù)據(jù)表:
(2.1) 找出系統(tǒng)表中錯誤記錄的ID
獲得AIS20030529181217中T_voucher表在sysobjects中的ID :
SELECT id FROM AIS20030529181217.dbo.sysobjects WHERE name=‘ t_voucher’
==》123
( 說明:通常即使sysobjects表損壞,不能做 select * from sysobjects 查詢,但是可以做 select ID,name from sysobjects 查詢。如果select ID,name from sysobjects 查詢也不能執(zhí)行,可以對照AisNew和AIS20030529181217兩個數(shù)據(jù)庫中的同名表: syscolumns。根據(jù)AisNew.dbo.syscolumns表中T_voucher所占字段的個數(shù)以及各個字段的名稱,在AIS20030529181217.dbo.syscolumns中找出T_voucher所對應(yīng)的記錄,由此獲得T_voucher在AIS20030529181217數(shù)據(jù)庫的系統(tǒng)表中所分配的ID。)
獲得AisNew中T_voucher表在sysobjects中的ID :
SELECT id FROM AisNew.dbo.sysobjects WHERE name=‘ t_voucher’
==》456
(2.2) 刪除AIS20030529181217中系統(tǒng)表中錯誤記錄:
DELETE AIS20030529181217.dbo.sysobjects WHERE id=123
DELETE AIS20030529181217.dbo.sysindexes WHERE id=123
DELETE AIS20030529181217.dbo.syscolumns WHERE id=123
(2.3) 重建系統(tǒng)表記錄
重建AIS20030529181217.dbo.sysobjects表中T_voucher表對應(yīng)的記錄:
INSERT INTO AIS20030529181217.dbo.sysobjects
(name,id,xtype,uid,info,status,base_schema_ver,replinfo,parent_obj,crdate,ftcatid)
SELECT
‘t_voucher_b’,123,xtype,uid,info,status,base_schema_ver,replinfo,parent_obj,crdate,ftcatid    
FROM  AisNew.dbo. sysobjects WHERE id=456
重建AIS20030529181217.dbo.sysindexes表中t_voucher表對應(yīng)的記錄:
INSERT INTO AIS20030529181217.dbo.sysindexes
(id,status,first,indid,root,minlen,keycnt,groupid,dpages,reserved,used,rowcnt,rowmodctr,reserved3,reserved4,xmaxlen,maxirow,OrigFillFactor,StatVersion,reserved2,FirstIAM,impid,lockflags,pgmodctr,keys,name,statblob) 
SELECT
123,status,first,indid,root,minlen,keycnt,groupid,dpages,reserved,used,rowcnt,rowmodctr,reserved3,reserved4,xmaxlen,maxirow,OrigFillFactor,StatVersion,reserved2,FirstIAM,impid,lockflags,pgmodctr,keys,name,statblob
FROM AisNew.dbo.sysindexes WHERE id=456
重建AIS20030529181217.dbo.syscolumns表中t_voucher表對應(yīng)的記錄:
INSERT INTO AIS20030529181217.dbo.syscolumns
(name,id,xtype,typestat,xusertype,length,xprec,xscale,colid,xoffset,bitpos,reserved,colstat,cdefault,domain,number,colorderby,autoval,offset,collationid,language)
SELECT
name,123,xtype,typestat,xusertype,length,xprec,xscale,colid,xoffset,bitpos,reserved,colstat,cdefault,domain,number,colORDERBY,autoval,offset,collationid,language
FROM AisNew.dbo.syscolumns WHERE id=456
(2.4)用DTS單獨將t_voucher_b表導(dǎo)入新的DataBase
經(jīng)過以上操作,AIS20030529181217中t_voucher_b 表與原t_voucher表共用同一ID。
試試看可否執(zhí)行SELECT * FROM t_voucher_b 查詢 —
如果可以,那么t_voucher_b就一定繼承原t_voucher表中的全部數(shù)據(jù)。再用INSERT INTO AisNew.dbo.T_voucher FROM AIS20030529181217.dbo.t_voucher_b
或DTS 將t_voucher_b中的數(shù)據(jù)導(dǎo)入AisNew。
  如果執(zhí)行SELECT * FROM t_voucher_b 查詢?nèi)匀粓箦e,這張表徹底沒戲了。
(2.5) 其他“不可訪問的數(shù)據(jù)表”處理方式同上,重復(fù)(2.1)~(2.4) 步。
*******修復(fù)系統(tǒng)表******
USE zygl3_data
GO
SELECT au.allocation_unit_id, OBJECT_NAME(p.object_id) AS table_name, fg.name AS filegroup_name,
au.type_desc AS allocation_type, au.data_pages, partition_number
FROM sys.allocation_units AS au
JOIN sys.partitions AS p ON au.container_id = p.partition_id
JOIN sys.filegroups AS fg ON fg.data_space_id = au.data_space_id
WHERE au.allocation_unit_id = 72057594055098368 OR au.allocation_unit_id = 72057594055098368
ORDER BY au.allocation_unit_id
GO