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

     

     

  • 相关阅读:
    ES6, CommonJS, AMD, CMD,UMD模块化规范介绍及使用
    前端项目开发框架选型需考虑的4个方面
    初识webSocket及其使用
    动态组件 —— 2种方式实现动态组件的切换
    mac下anaconda安装新包
    新版docker设置国内镜像
    记一次解决Original error: UiAutomator quit before it successfully launched
    linux clion cmakelisits undefined reference 未定义引用
    苹果设备插入PC不能识别问题解决办法
    用Cucumber理解BDD行为驱动开发
  • 原文地址:https://www.cnblogs.com/kerrycode/p/8743371.html
Copyright © 2011-2022 走看看