天天看點

SQL Server中繼資料損壞(metadata corruption)修複

原文: 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.

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'.

SQL Server中繼資料損壞(metadata corruption)修複

那麼我們先找到系統視圖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系統基礎表。

SQL Server中繼資料損壞(metadata corruption)修複

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

EXEC sp_configure 'allow_updates', 1;

RECONFIGURE WITH OVERRIDE;

GO

USE TEST;

DELETE FROM  sys.syscolpars WHERE id=1362819917;

SQL Server中繼資料損壞(metadata corruption)修複

那麼難道就沒有辦法解決這種問題了嗎? 答案是當然有,不過,這種方式是沒有官方文檔而且也不被官方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)      
SQL Server中繼資料損壞(metadata corruption)修複

此時再去檢查資料庫一緻性,你就會看到上面遇到的中繼資料損壞錯誤不見了。如下截圖所示:

SQL Server中繼資料損壞(metadata corruption)修複

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