5

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

由于许可证到期重新安装 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 状态无效。

有没有办法解决这个问题?

任何想法表示赞赏。

4

2 回答 2

6

嗨,要修复 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
于 2013-05-12T04:44:50.230 回答
0

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

于 2013-02-17T00:24:21.923 回答