SQL Server元數據損壞(metadata corruption)修復


 

在升級一個SQL Server 2000的數據庫時,遇到了一致性錯誤,其中有幾個錯誤是元數據損壞(metadata corruption),特意研究了一下這個案例,因為以前也零零散散的遇到過一些一致性相關錯誤,但是難得遇到元數據損壞的案例。

 

如下所示,數據庫從SQL Server 2000還原到SQL Server 2008以后,在做一致性檢查時,發現有元數據損壞(metadata corruption),下面是實驗是構造的一個測試環境

 

DBCC CHECKCATALOG (TEST) WITH NO_INFOMSGS;
GO
 
DBCC CHECKDB(TEST) WITH NO_INFOMSGS;
GO

 

 

Msg 8992, Level 16, State 1, Line 1

Check Catalog Msg 3853, State 1: Attribute (object_id=1362819917) of row (object_id=1362819917,parameter_id=1) in sys.parameters does not have a matching row (object_id=1362819917) in sys.objects.

Msg 8992, Level 16, State 1, Line 1

Check Catalog Msg 3853, State 1: Attribute (object_id=1362819917) of row (object_id=1362819917,parameter_id=2) in sys.parameters does not have a matching row (object_id=1362819917) in sys.objects.

CHECKDB found 0 allocation errors and 2 consistency errors not associated with any single object.

CHECKDB found 0 allocation errors and 2 consistency errors in database 'TEST'.

 

 

 

clip_image001

 

 

 

 

那么我們先找到系統視圖sys.parameters的數據來源於那個系統基礎表(System Base-Table Metadata),如下腳本所示,我們可以找到sys.parameters 最終來源於sys.syscolpars和 sys.sysobjvalues(關於如何獲取系統視圖定義,此處不做展開分析)

 

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE VIEW sys.parameters AS
    SELECT object_id, name,
        parameter_id, system_type_id,
        user_type_id, max_length,
        precision, scale,
        is_output, is_cursor_ref,
        has_default_value, is_xml_document,
        default_value, xml_collection_id,
        is_readonly
    FROM sys.parameters$
    WHERE number = 1
 
GO
 
 
 
CREATE VIEW sys.parameters$ AS
    SELECT c.id AS object_id,
        c.number, c.name,
        c.colid AS parameter_id,
        c.xtype AS system_type_id,
        c.utype AS user_type_id,
        c.length AS max_length,
        c.prec AS precision,
        c.scale AS scale,
        sysconv(bit, c.status & 512) AS is_output,        -- CPM_OUTPUT
        sysconv(bit, c.status & 1024) AS is_cursor_ref,    -- CPM_CURSORREF
        sysconv(bit, isnull(v.objid, 0)) AS has_default_value,
        sysconv(bit, c.status & 2048) AS is_xml_document, -- CPM_XML_DOC        
        v.value AS default_value,
        xmlns AS xml_collection_id,
        sysconv(bit, c.status & 4194304) AS is_readonly -- CPM_IS_READONLY = 0x00400000
    FROM sys.syscolpars c
    LEFT JOIN sys.sysobjvalues v ON v.valclass = 9 AND v.objid = c.id AND v.subobjid = c.colid AND v.valnum = 0    -- SVC_PARAMDEFAULT
    WHERE number > 0 AND has_access('CO', c.id) = 1

 

 

但是系統基礎表sys.syscolpars和sys.sysobjvalues在正常情況下是不可見的。只有在數據庫專用管理員連接方式(DAC Dedicated Administrator Connection)連接下才能可見。如下所示,可以判斷數據來源於sys.syscolpars系統基礎表。

 

 

clip_image002

 

 

此時即使在專用管理員連接下面也是無法刪除這些數據的,會報Ad hoc update to system catalogs is not supported,對應中文提示為不支持對系統目錄進行即席更新。如下所示:

 

 

EXEC sp_configure 'allow_updates', 1;

RECONFIGURE WITH OVERRIDE;

GO

USE TEST;

GO

DELETE FROM  sys.syscolpars WHERE id=1362819917;

GO

 

 

clip_image003

 

 

 

那么難道就沒有辦法解決這種問題了嗎? 答案是當然有,不過,這種方式是沒有官方文檔而且也不被官方Support的,如果你要按下面方法操作,是有一定風險的。所以如果你決定按照下面方式修復元數據損壞的話,先做好備份。以防萬一

 

你必須將數據庫實例在單用戶模式下面啟動,然后以專用管理員(DAC)連接到數據庫,然后就可以刪除基礎表下面的數據了,如下截圖所示:

 

 

C:\Documents and Settings>net stop mssqlserver

The SQL Server (MSSQLSERVER) service is stopping.

The SQL Server (MSSQLSERVER) service was stopped successfully.

 

 

C:\Documents and Settings>net start mssqlserver /m"Microsoft SQL Serve

r Management Studio - Query"

The SQL Server (MSSQLSERVER) service is starting.

The SQL Server (MSSQLSERVER) service was started successfully.

 

 

USE TEST;
GO
DELETE FROM  sys.syscolpars WHERE id=1362819917;
GO
 
----------------------------------------------------------------------------------
Warning: System table ID 41 has been updated directly in database ID 5 and cache coherence may not have been maintained. SQL Server should be restarted.
 
(2 row(s) affected)

 

clip_image004

 

 

 

此時再去檢查數據庫一致性,你就會看到上面遇到的元數據損壞錯誤不見了。如下截圖所示:

 

 

 

clip_image005

 

 

其實如果是從SQL Server 2000還原的話,在SQL Server 2000當中是可以修改相關系統表的,如果執行了DBCC CHECKDB命令發現了元數據問題,那么可以直接修改系統表解決問題(當然只是部分情況),如果已經還原到了SQL Server 2008 以上數據庫時,就必須按這種方式折騰,由於這種方式,官方是不支持的。所以還是有一定風險的。因為你不清楚潛在的風險,也不能確保任何場景都能解決問題而不出現意外情況。所以操作之前,盡量多測試、做好備份以防萬一。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM