zoukankan      html  css  js  c++  java
  • 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 以上数据库时,就必须按这种方式折腾,由于这种方式,官方是不支持的。所以还是有一定风险的。因为你不清楚潜在的风险,也不能确保任何场景都能解决问题而不出现意外情况。所以操作之前,尽量多测试、做好备份以防万一。

     

     

  • 相关阅读:
    Insus Meta Utility
    The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
    Insus Binary Utility
    asp.net实现文件下载功能
    Column 'Column Name' does not belong to table Table
    程序已被编译为DLL,怎样去修改程序功能
    如何在Web网站实现搜索功能
    如何把数据流转换为二进制字符串
    Asp.net更新文件夹的文件
    如何显示中文月份
  • 原文地址:https://www.cnblogs.com/kerrycode/p/8743371.html
Copyright © 2011-2022 走看看