【问题标题】:CDC fails after attaching database to SQL Server 2008 R2 instance将数据库附加到 SQL Server 2008 R2 实例后,CDC 失败
【发布时间】:2013-02-16 22:50:50
【问题描述】:

我们在 SQL Server 2008 R2 (SP 1) 上托管了一个 SQL Server 数据库,并启用了 CDC(变更数据捕获)。

由于许可证到期重新安装 SQL Server 实例后(部署团队忘记安装正确的许可证 :( )我们将数据库附加到新安装的实例。

但是,并非所有表都启用了 CDC 当我们尝试通过执行来启用它时

sys.sp_cdc_enable_table

我们得到了

数据库“DBName”未启用变更数据捕获。确保 设置正确的数据库上下文并重试该操作。到 报告启用变更数据捕获的数据库,查询 sys.databases 目录视图中的 is_cdc_enabled 列。

提示 CDC 未启用。

所以,我们尝试通过执行来启用它

sys.sp_cdc_enable_db

我们收到以下错误:

消息 22906,级别 16,状态 1,过程 sp_cdc_enable_db_internal, 49号线
无法为更改数据启用数据库“DBName” 捕获因为名为“cdc”的数据库用户或名为“cdc”的模式 当前数据库中已经存在。这些对象是必需的 由变更数据捕获独家提供。删除或重命名用户或架构 并重试该操作。

在尝试通过执行禁用 CDC 之后

sys.sp_cdc_disable_db

我们又遇到了同样的错误:

数据库“DBName”未启用变更数据捕获。确保 设置正确的数据库上下文并重试该操作。到 报告启用变更数据捕获的数据库,查询 sys.databases 目录视图中的 is_cdc_enabled 列。

我的猜测是 db 系统表和 SQL server 系统表之间存在一些不一致导致 CDC 状态无效。

有什么办法可以解决吗?

感谢任何想法。

【问题讨论】:

    标签: sql-server sql-server-2008 sql-server-2008-r2


    【解决方案1】:

    你好 用于修复 Db(删除 cdc 架构和架构本身中的所有内容) 使用这个:

    DECLARE @tableName NVARCHAR(100);
    DECLARE myCursor CURSOR FORWARD_ONLY FAST_FORWARD READ_ONLY
    FOR
        SELECT  QUOTENAME(t.name) AS name
        FROM    sys.tables t
                JOIN sys.schemas s ON t.schema_id = s.schema_id
        WHERE   s.name = 'cdc'
    OPEN myCursor 
    FETCH FROM myCursor INTO @TableName 
    WHILE ( @@Fetch_Status = 0 ) 
        BEGIN 
    
            EXEC ( 'drop table cdc.' + @TableName + '; ' );
            FETCH NEXT FROM myCursor INTO @TableName 
        END  
    CLOSE myCursor 
    DEALLOCATE myCursor;
    go
    
    DECLARE @prName NVARCHAR(100);
    DECLARE myCursor2 CURSOR FORWARD_ONLY FAST_FORWARD READ_ONLY
    FOR
        SELECT  QUOTENAME(pr.name) AS name
        FROM    sys.procedures pr
                JOIN sys.schemas s ON pr.schema_id = s.schema_id
        WHERE   s.name = 'cdc'
    OPEN myCursor2 
    FETCH FROM myCursor2 INTO @prName 
    WHILE ( @@Fetch_Status = 0 ) 
        BEGIN 
            EXEC ( 'drop procedure cdc.' + @prName + '; ' );
            FETCH NEXT FROM myCursor2 INTO @prName 
        END  
    CLOSE myCursor2
    DEALLOCATE myCursor2 
    
    GO
    
    DECLARE @fnName NVARCHAR(100);
    DECLARE myCursor3 CURSOR FORWARD_ONLY FAST_FORWARD READ_ONLY
    FOR
        SELECT  QUOTENAME(fn.name) AS name
        FROM    sys.objects fn
                JOIN sys.schemas s ON fn.schema_id = s.schema_id
        WHERE   fn.type IN ( 'FN', 'IF', 'TF' )
                AND s.name = 'cdc'
    OPEN myCursor3 
    FETCH FROM myCursor3 INTO @fnName 
    WHILE ( @@Fetch_Status = 0 ) 
        BEGIN 
            EXEC ( 'drop function cdc.' + @fnName + '; ' );
            FETCH NEXT FROM myCursor3 INTO @fnName 
        END  
    CLOSE myCursor3
    DEALLOCATE myCursor3 
    go
    DECLARE @ruleName NVARCHAR(100);
    SELECT  @ruleName = DP1.name
    FROM    sys.database_principals AS DP1
            JOIN sys.database_principals AS DP2 ON DP1.owning_principal_id = DP2.principal_id
    WHERE   DP1.type = 'R'
            AND DP2.name = 'cdc';
    EXEC ('ALTER AUTHORIZATION ON ROLE::'+@ruleName+' TO dbo; ')
    go 
    DROP SCHEMA [cdc]
    GO
    DROP USER [cdc]
    GO
    

    【讨论】:

    • 工作得很好,除了如果根本没有规则,在我的情况下,我得到一个 NULL,这个语句失败...... EXEC ('ALTER AUTHORIZATION ON ROLE::'+@ruleName+' TO dbo ; ')
    • 根据this 文章,这是SQL server 中的一个bug。但是,我发现即使是带有 cu17 的 SQL 2017 仍然存在同样的问题。这个脚本帮助修复了它。
    【解决方案2】:

    我也遇到过处理 CDC 启用/禁用的糟糕方法。如果我是你,我会尝试删除 cdc 架构和架构本身中的所有内容,然后尝试再次在数据库中启用 CDC。或者,如果您正在恢复(而不是附加),则有一个 KEEP_CDC 选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多