CDC 的已知限制、问题和错误

适用于: SQL Server Azure SQL 托管实例

本文介绍 SQL ServerAzure SQL 托管实例变更数据捕获的已知限制、问题和错误。

有关 Azure SQL 数据库,请参阅 Azure SQL 数据库中的 CDC 已知问题

修改元数据

要使 CDC 正常运行,不应手动修改任何 CDC 元数据,如 CDC schema、更改表、CDC 系统存储过程、默认 cdc user 用户权限 (sys.database_principals) 或重命名 cdc user

不应修改 sys.objectsis_ms_shipped 属性设置为 1 的任何对象。

SELECT    name AS object_name   
        ,SCHEMA_NAME(schema_id) AS schema_name  
        ,type_desc  
        ,is_ms_shipped  
FROM sys.objects 
WHERE is_ms_shipped= 1 AND SCHEMA_NAME(schema_id) = 'cdc'

排序规则差异

请务必了解在数据库与为变更数据捕获而配置的表的列之间具有不同的排序规则。 CDC 使用临时存储来填充副表。 如果表的 CHAR 或 VARCHAR 列的排序规则与数据库排序规则不同,并且这些列存储了非 ASCII 字符(例如双字节 DBCS 字符),则 CDC 可能无法将更改后的数据与基表中的数据保持一致。 这是因为临时存储变量不能包含与之关联的排序规则。

请考虑以下方法之一,确保捕获的更改数据与基表保持一致:

  • 将 NCHAR 或 NVARCHAR 数据类型用于包含非 ASCII 数据的列。

  • 或者,将相同的排序规则用于列和数据库。

例如,如果有使用 SQL_Latin1_General_CP1_CI_AS 排序规则的数据库,请考虑下表:

CREATE TABLE T1( 
     C1 INT PRIMARY KEY, 
     C2 VARCHAR(10) collate Chinese_PRC_CI_AI)

CDC 可能无法为列 C2 捕获二进制数据,因为它的排序规则不同 (Chinese_PRC_CI_AI)。 使用 NVARCHAR 可避免此问题:

CREATE TABLE T1( 
     C1 INT PRIMARY KEY, 
     C2 NVARCHAR(10) collate Chinese_PRC_CI_AI --Unicode data type, CDC works well with this data type
     )

加速数据库恢复(ADR)和变更数据捕获(CDC)

目前不支持启用变更数据捕获 (CDC) 和加速数据库恢复 (ADR)。 在 SQL Server 上启用变更数据捕获 (CDC) 时,ADR 的主动日志截断功能将被禁用。 这是因为 CDC 扫描访问数据库事务日志。 活动事务将继续保留事务日志截断,直到事务提交并且 CDC 扫描跟上进度,或事务中止。 这可能会导致各种问题,包括事务日志填满问题超过正常情况或侧表中记录的数据操作出现异常。

在启用 CDC 时,建议使用“可恢复索引”选项。 可恢复索引不要求长时间运行的事务一直处于打开状态即可创建或重新生成索引,允许在此操作期间执行日志截断,并提升日志空间管理效果。 有关详细信息,请参阅联机索引操作指南 - 可恢复索引注意事项

不支持联机 DDL 语句

在数据库上启用更改数据捕获时,不支持联机 DDL 语句

如果已存在架构或名为 cdc 的用户,则启用 CDC 失败

在数据库上启用 CDC 时,会创建新架构和名为 cdc 的用户。 因此,不建议手动创建自定义架构或名为 cdc 的用户,因为它保留供系统使用。

如果你在数据库中手动定义了与 CDC 无关的自定义架构或名为 cdc 的用户,则系统存储过程 sys.sp_cdc_enable_db 无法在数据库上启用 CDC,并显示以下错误消息。

因为当前数据库中已存在名为 'cdc' 的数据库用户或名为 'cdc' 的架构,所以无法为变更数据捕获启用数据库 <database_name>。 CDC 需要独占使用这些对象。 请删除或重命名该用户或架构,然后重试相应操作。

若要解决此问题,请执行下列操作:

  • 手动删除空的 cdc 架构和 cdc 用户。 然后,你可以在数据库上成功启用 CDC。

在 ALTER COLUMN 到 VARCHAR 和 VARBINARY 之后 CDC 失败

在启用 CDC 的表上的列的数据类型从 TEXT 更改为 VARCHAR 或从 IMAGE 更改为 VARBINARY 时,现有行会更新为行外值。 在更新后,CDC 扫描将导致错误。

对源表的 DDL 更改

使用 DDL 语句更改已启用 CDC 的表的列大小可能会导致后续 CDC 捕获过程出现问题,从而导致错误 2628 或错误 8115。 请记住,CDC 更改表中的数据会根据用户配置的设置保留。 因此,在对列大小进行任何更改之前,你必须评估更改是否与 CDC 更改表中的现有数据兼容。

如果 sys.dm_cdc_errors 指示扫描由于更改表的错误 2628错误 8115 而失败,你应先使用受影响更改表中的更改数据。 之后,需要禁用并重新启用表上的 CDC,以有效地解决问题。

使用数据层导入/导出和提取/发布操作来导入数据库

对于启用了 CDC 的 SQL 数据库,在使用 SqlPackage、SSDT 或其他 SQL 工具导入/导出或提取/发布时,新数据库中将排除 cdc 架构和用户。 导入/导出和提取/部署操作中未包含的其他 CDC 对象包括在 sys.objects 中标记为 is_ms_shipped=1 的表。

即使未启用 CDC,且已在数据库中定义自定义架构或名为 cdc 的用户,该架构或用户也将在导入/导出和提取/部署操作中排除以导入/设置新数据库。

使用变量进行分区切换

对于 ALTER TABLE ... SWITCH TO ... PARTITION ... 语句,不支持在带有变更数据捕获 (CDC) 的数据库或表上使用带有分区切换的变量。 有关详细信息,请参阅分区切换限制

解决错误

本部分分步排查与 SQL Server 和 Azure SQL 托管实例上的 CDC 关联的错误。 与 CDC 相关的错误可能会阻碍捕获过程的正常运行,并导致数据库事务日志的扩展。

要检查这些错误,你可以查询动态管理视图 sys.dm_cdc_errors。 如果 sys.dm_cdc_errors 动态管理视图返回任何错误,请参阅以下部分,了解缓解步骤。

注意

有关特定错误代码的详细信息,请参阅数据库引擎事件和错误

以下是本部分中包含的不同疑难解答类别:

类别 说明
已修改的元数据 包括有关如何在修改或删除跟踪表时缓解与 CDC 相关的问题的信息。
数据库空间管理 包括有关如何在数据库空间用完时缓解问题的信息。
CDC 限制 包括有关如何缓解 CDC 限制导致的问题的信息。

已修改的元数据

错误 200/208 - 对象名称无效。

  • 原因:在删除 CDC 元数据后,可能会出现此错误。 要使 CDC 正常运行,不应手动修改任何 CDC 元数据,如 CDC schema、更改表、CDC 系统存储过程、默认 cdc user 用户权限 (sys.database_principals) 或重命名 cdc user

  • 建议:要解决此问题,需要为数据库禁用并重新启用 CDC。 当为某个数据库启用变更数据捕获时,将为该数据库创建 cdc 架构、cdc 用户、元数据表和其他系统对象。

注意

不应更改或删除在 sys.objects 系统目录视图中发现的 is_ms_shipped=1 且 schema_name='cdc' 的对象。

错误 1202 - 数据库主体不存在,或者用户不是成员

  • 原因:在删除 CDC 用户后,可能会出现此错误。 要使 CDC 正常运行,不应手动修改任何 CDC 元数据,如 CDC schema、更改表、CDC 系统存储过程、默认 cdc user 用户权限 (sys.database_principals) 或重命名 cdc user

  • 建议:确保 cdc 用户存在于数据库中,并且还分配了 db_owner 角色。 要创建 cdc 用户,请参阅示例创建 cdc 用户并分配角色

错误 15517 - 无法作为数据库主体执行,因为主体不存在。

  • 原因:无法模拟此类主体,或者你没有权限。 在删除 CDC 元数据或其已不再属于 db_owner 角色时,可能会出现此错误。 要使 CDC 正常运行,不应手动修改任何 CDC 元数据,如 CDC schema、更改表、CDC 系统存储过程、默认 cdc user 用户权限 (sys.database_principals) 或重命名 cdc user

  • 建议:确保 cdc 用户存在于数据库中,并且还分配了 db_owner 角色。 要创建 cdc 用户,请参阅示例创建 cdc 用户并分配角色

错误 18807 - 找不到复制系统表的对象 ID。

  • 原因:当 SQL Server 找不到或无法访问复制系统表 '%s' 时,会发生此错误。 这可能是因为表缺少或无法访问。 要使 CDC 正常运行,不应手动修改任何 CDC 元数据,如 CDC schema、更改表、CDC 系统存储过程、默认 cdc user 用户权限 (sys.database_principals) 或重命名 cdc user

  • 建议:请验证该系统表是否存在,以及是否可以通过直接查询表进行访问。 查询 sys.objects 系统目录,使用 is_ms_shipped=1 和 schema_name='cdc' 将谓词子句设置为列出所有与 CDC 相关的对象。 如果查询未返回任何对象,则应禁用并重新为数据库启用 CDC。 为某个数据库启用变更数据捕获,会为该数据库创建 cdc 架构、cdc 用户、元数据表和其他系统对象。

错误 21050 - 只有 sysadmin 或 db_owner 固定服务器角色的成员才能执行此操作

  • 原因cdc 用户已从 db_owner 数据库角色或 sysadmin 服务器角色中删除。

  • 建议:确保 cdc 用户已分配 db_owner 角色。 要创建 cdc 用户,请参阅示例创建 cdc 用户并分配角色

数据库空间管理

错误 1105 - 由于文件组已满,无法为数据库中的对象分配空间

  • 原因:当数据库主文件组的空间耗尽,并且 SQL Server 无法为该文件组中的对象(如表或索引)分配更多空间时,会发生此错误。

  • 建议:要解决此问题,请删除数据库中任何不必要的数据以释放空间。 确定文件组中可以安全删除的未使用的表、索引或其他对象。 密切监视空间利用率,有关详细信息,请参阅管理 Azure SQL 数据库中数据库的文件空间

    如果无法删除不必要的数据/对象,请考虑为数据库事务日志分配更多空间。 有关事务日志管理的详细信息,请参阅 SQL Server 事务日志体系结构和管理指南

CDC 限制

错误 2628 — 字符串或二进制数据在表中会被截断

  • 原因:使用 DDL 语句更改已启用 CDC 的表的列大小可能会导致后续 CDC 捕获过程出现问题。 'sys.dm_cdc_errors' 动态管理视图 (DMV) 对于任何报告的问题(如错误号 2628 和 8115)检查任何 CDC 非常有用。

  • 建议:在对列大小进行任何更改之前,你必须评估更改是否与 CDC 更改表中的现有数据兼容。 要解决此问题,需要为数据库禁用并重新启用 CDC。 有关为数据库或表启用 CDC 的详细信息,请参阅为数据库启用 CDC为表启用 CDC

错误 913 - 在处理具有系统 CLR 数据类型的表的更改时,CDC 捕获作业失败

  • 原因:当在具有系统 CLR 数据类型的表上启用 CDC、进行 DML 更改,然后在 CDC 捕获作业处理与其他表相关的更改时对同一表进行 DDL 更改,就会发生此错误。

  • 建议:建议的步骤是暂停表中的 DML 处理,运行捕获作业来处理更改,为表运行 DDL,运行捕获作业以处理 DDL 更改,然后重新启用 DML 处理。 有关详细信息,请参阅在处理更改时 CDC 捕获作业失败

创建用户和分配角色

如果已删除 cdc user,可以手动添加回用户。

使用以下 T-SQL 脚本创建用户 (cdc),并为同一用户 (db_owner) 分配适当的角色。

IF NOT EXISTS 
(
    SELECT * 
    FROM sys.database_principals 
    WHERE NAME = 'cdc'
)
BEGIN
    CREATE USER [cdc] 
    WITHOUT LOGIN WITH DEFAULT_SCHEMA = [cdc];
END

EXEC sp_addrolemember 'db_owner', 'cdc';

检查和添加角色成员身份

要验证 cdc 用户是否属于 sysadmindb_owner 角色,请运行以下 T-SQL 查询:

EXECUTE AS USER = 'cdc';

SELECT is_srvrolemember('sysadmin'), is_member('db_owner');

如果 cdc 用户不属于任一角色,请执行以下 T-SQL 查询,以将 db_owner 角色添加到 cdc 用户。

EXEC sp_addrolemember 'db_owner' , 'cdc';

后续步骤