本文介绍 SQL Server 和 Azure SQL 托管实例在更改数据捕获(CDC)过程中的已知限制、问题和错误。
有关 Azure SQL 数据库,请参阅 Azure SQL 数据库中的 CDC 已知问题。
修改元数据
若要使 CDC 正常运行,不应手动修改任何 CDC 元数据,例如 CDC schema、更改表、CDC 系统存储过程、默认 cdc user 权限(sys.database_principals)或重命名 cdc user。
不应修改 sys.objects 中 is_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 可能无法保证更改的数据与基表中的数据保持一致。 这是因为临时存储变量不能包含与之关联的排序规则。
请考虑以下方法之一,确保捕获的更改数据与基表保持一致:
对包含非 ASCII 数据的列使用 nchar 或 nvarchar 数据类型。
或者,将相同的排序规则用于列和数据库。
例如,如果有使用 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)
SQL Server 2019(15.x)不支持为同一数据库启用变更数据捕获(CDC)和加速数据库恢复(ADR)。 从 SQL Server 2022 (16.x) 累积更新 18 开始,后续 SQL Server 版本支持启用 CDC 和 ADR。
启用 CDC 时,ADR 的主动日志截断功能将被禁用。 这是因为 CDC 扫描访问数据库事务日志。 活动事务将继续保留事务日志截断,直到事务提交并且 CDC 扫描跟上进度,或事务中止。 如果在启用了 ADR 的数据库上启用 CDC,则可能会看到更高的事务日志利用率。 确保有足够的事务日志空间满足所有工作负荷的需求。
如果已存在架构或已命名 cdc 的用户,则启用 CDC 失败
在数据库上启用 CDC 时,会创建新架构和名为 cdc 的用户。 因此,不建议手动创建名为 cdc 的自定义架构或用户,因为它保留供系统使用。
如果已在数据库中手动定义了与 CDC 无关的 cdc 的自定义架构或用户,则系统存储过程 sys.sp_cdc_enable_db 无法对数据库启用 CDC,并显示以下错误消息。
The database <database_name> cannot be enabled for change data capture because a database user named 'cdc' or a schema named 'cdc' already exists in the current database. These objects are required exclusively by CDC. Drop or rename the user or schema and retry the operation.
若要解决此问题,请执行下列操作:
- 手动删除空的
cdc架构和cdc用户。 然后,你可以在数据库上成功启用 CDC。
执行 ALTER COLUMN 后 CDC 失败
当启用了 CDC 的表上的列的数据类型更改为不受支持的转换类型时,更新后可能会导致 CDC 扫描出错。
下面是在表上启用 CDC 时不支持的数据类型更改的示例 ALTER COLUMN :
- bigint 转换为 int
- char(x)、 nvarchar(x)或 nvarchar(x) 更改为 uniqueidentifier、 DATE 或 INT
更改启用了 CDC 的表中列的数据类型可能会导致以下错误:
使用 DDL 语句更改已启用 CDC 的表的列大小可能会导致后续 CDC 捕获过程出现问题,从而导致以下错误:
请记住,CDC 更改表中的数据会根据用户配置的设置保留。 因此,在对列大小进行任何更改之前,你必须评估更改是否与 CDC 更改表中的现有数据兼容。
sys.dm_cdc_errors如果显示扫描因错误 2628或者错误 8115导致更改表失败,您应首先使用好受影响更改表中的更改数据。 之后,需要禁用并重新启用表上的 CDC,以有效地解决问题。
当 CREATE OBJECT 触发器存在时启用 CDC 失败
启用 CDC 时会创建一个 cdc user 来管理 CDC 创建过程。
cdc user 运行许多存储过程来启用 CDC,其中一些存储过程创建触发现有 CREATE OBJECT 触发器的对象。 由于 cdc user 无权写入 master 数据库,因此这些 CDC 存储过程失败并出现错误 22830。
在启用数据库上的 CDC 之前,禁用任何 CREATE OBJECT 触发器。 配置 CDC 后,重新启用这些触发器。
使用数据层导入/导出和提取/发布操作来导入数据库
对于启用了 CDC 的 SQL 数据库,在使用 SqlPackage、SSDT 或其他 SQL 工具导入/导出或提取/发布时,新数据库中将排除 cdc 架构和用户。 导入/导出和提取/部署作中未包含的其他 CDC 对象包括标记为 is_ms_shipped=1 In sys.objects的表。
即使未启用 CDC,且已在数据库中定义自定义架构或名为 cdc 的用户,该架构或用户也将在导入/导出和提取/部署操作中排除以导入/设置新数据库。
使用变量进行分区切换
对于 ALTER TABLE ... SWITCH TO ... PARTITION ... 语句,不支持在带有变更数据捕获 (CDC) 的数据库或表上使用带有分区切换的变量。 有关详细信息,请参阅分区切换限制。
联机作
不支持联机 DDL 语句
在 SQL Server 2025(17.x) 预览版之前的 Azure SQL 托管实例和 SQL Server 版本中,在数据库上启用更改数据捕获时, 不支持 ALTER TABLE 联机 DDL 语句 。
不支持联机索引作
在数据库上启用更改数据捕获时,不支持联机索引作。 可能会遇到错误 18773“找不到列的文本信息记录”%.*ls“,命令构造期间 ID %d。
新增列的默认约束
在表上启用 CDC 并且添加了具有默认约束的不可为 null 列时,现有行数据将具有默认约束的值。 但是,CDC 将对NULL使用,而不是默认值。 这仅适用于应用 DDL 之前存在的数据。 解决方法是,对现有行发出非更改 UPDATE 语句,或者对表的聚集索引进行 ALTER INDEX ... REBUILD 操作。 如果没有聚集索引,则对堆使用 ALTER TABLE ... REBUILD 。
Troubleshooting
本部分分步排查与 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 and schema_name='cdc' 找到的对象。
错误 1202 - 数据库主体不存在,或者用户不是成员
原因:删除
cdc user时可能会出现此错误。 若要使 CDC 正常运行,不应手动修改任何 CDC 元数据,例如CDC schema更改表、CDC 系统存储过程、默认cdc user权限或重命名。cdc user建议:确保
cdc用户存在于数据库中,并且还分配了db_owner角色。 要创建cdc用户,请参阅示例创建 cdc 用户并分配角色。
错误 15517 - 无法作为数据库主体执行,因为主体不存在。
原因:无法模拟此类主体,或者你没有相应权限。 在删除 CDC 元数据或其已不再属于
db_owner角色时,可能会出现此错误。 若要使 CDC 正常运行,不应手动修改任何 CDC 元数据,例如CDC schema更改表、CDC 系统存储过程、默认cdc user权限或重命名。cdc user建议:确保
cdc用户存在于数据库中,并且还分配了db_owner角色。 要创建cdc用户,请参阅示例创建 cdc 用户并分配角色。
错误 18807 - 找不到复制系统表的对象 ID。
原因:当 SQL Server 找不到或无法访问复制系统表 '%s' 时,会发生此错误。 这可能是因为表缺少或无法访问。 若要使 CDC 正常运行,不应手动修改任何 CDC 元数据,例如
CDC schema更改表、CDC 系统存储过程、默认cdc user权限或重命名。cdc user建议:请验证该系统表是否存在,以及是否可以通过直接查询表进行访问。 查询 sys.objects 系统目录,将谓词子句设置为
is_ms_shipped=1 and schema_name='cdc'列出所有与 CDC 相关的对象。 如果查询未返回任何对象,则应禁用并重新为数据库启用 CDC。 为某个数据库启用变更数据捕获,会为该数据库创建 cdc 架构、cdc 用户、元数据表和其他系统对象。
错误 21050 - 只有 sysadmin 或 db_owner 固定服务器角色的成员才能执行此操作
原因:
cdc user已从db_owner数据库角色或sysadmin服务器角色中删除。建议:确保为 分配了
cdc user角色db_owner。 要创建cdc用户,请参阅示例创建 cdc 用户并分配角色。
错误 22830 - 无法更新元数据来指示已对数据库 <database name> 启用了变更数据捕获。 执行命令 <CDC stored procedure name>时发生失败。
原因:当数据库或服务器上存在触发器时
CREATE OBJECT,会发生此错误。 启用 CDC 时会创建一个cdc user来管理 CDC 创建过程。cdc user运行许多存储过程来启用 CDC,其中一些存储过程创建触发现有CREATE OBJECT触发器的对象。 由于cdc user无权写入master数据库,因此这些 CDC 存储过程失败并出现错误 22830。建议:在数据库上启用 CDC 之前,请禁用任何
CREATE OBJECT触发器。 配置 CDC 后,再次重新启用这些触发器。
数据库空间管理
错误 1105 - 由于文件组已满,无法为数据库中的对象分配空间
原因:当数据库主文件组的空间耗尽,并且 SQL Server 无法为该文件组中的对象(如表或索引)分配更多空间时,会发生此错误。
建议:要解决此问题,请删除数据库中任何不必要的数据以释放空间。 确定文件组中可以安全删除的未使用的表、索引或其他对象。 密切监视空间利用率,有关详细信息,请参阅管理 Azure SQL 数据库中数据库的文件空间
如果无法删除不必要的数据/对象,请考虑为数据库事务日志分配更多空间。 有关事务日志管理的详细信息,请参阅 SQL Server 事务日志体系结构和管理指南
CDC 限制
错误 241 - 从字符串转换日期和时间时转换失败
原因:当 ALTER COLUMN 对 日期 数据类型执行并且表启用了 CDC 时,会发生此错误。 例如,如果表具有 nvarchar 列并将数据类型更改为 日期 (例如),
ALTER TABLE table_name ALTER COLUMN [column_name] DATE NULL则可能在 sys.dm_cdc_errors DMV 中看到此错误。 错误 241 是由于更改表中的数据转换不受支持,即使ALTER源表上的命令成功。建议:若要解决此问题,请在更改列后为表禁用并重新启用 CDC。 或者,在更改列之前禁用 CDC,然后在更改后
ALTER COLUMN重新启用 CDC。
错误 245 - 将值从字符串转换为 int 时转换失败
原因:当发出 ALTER COLUMN 命令以在表启用了 CDC 时更改列的数据类型时,会发生此错误。 例如,如果表具有 nvarchar 列,并将数据类型更改为 int (例如),
ALTER TABLE table_name ALTER COLUMN [column_name] INT NULL则可能在 sys.dm_cdc_errors DMV 中看到此错误。 错误 245 是由于更改表中的数据转换不受支持,即使ALTER源表上的命令成功。建议:若要解决此问题,请在更改列后为表禁用并重新启用 CDC。 或者,在更改列之前禁用 CDC,然后在更改后
ALTER COLUMN重新启用 CDC。
错误 913 - 当处理具有系统 CLR 数据类型的表的更改时,CDC 捕获作业失败
原因:在具有系统 CLR 数据类型的表上启用 CDC、进行 DML 更改,然后在 CDC 捕获作业处理与其他表相关的更改时对同一表进行 DDL 更改时,会发生此错误。
建议:建议的步骤是暂停表中的 DML 处理,运行捕获作业来处理更改,为表运行 DDL,运行捕获作业以处理 DDL 更改,然后重新启用 DML 处理。 有关详细信息,请参阅 CDC 捕获作业 在处理具有系统 CLR 数据类型(geometry、 geography 或 hierarchyid)的表更改时失败。
错误 2628 — 字符串或二进制数据在表中会被截断
原因:使用 DDL 语句更改启用了 CDC 的表的列的大小可能会导致后续 CDC 捕获过程出现问题。 sys.dm_cdc_errors 动态管理视图(DMV)对于检查 CDC 中的任何报告问题(例如错误编号 2628 和 8115)非常有用。
建议:在对列大小进行任何更改之前,你必须评估更改是否与 CDC 更改表中的现有数据兼容。 要解决此问题,需要为数据库禁用并重新启用 CDC。 有关为数据库或表启用 CDC 的详细信息,请参阅 为数据库启用 CDC,为表启用 CDC。
错误 8115 - 算术溢出错误,在将数据类型从 bigint 转换为 int 时发生
原因:如果在启用了 CDC 的表中执行 ALTER COLUMN DDL,导致列的精度降低(例如将列的数据类型从 bigint 更改为 int),则会发生此错误。 降低精度的列无法保存更改表中存在的值。
建议:若要解决此问题,请在更改列后为表禁用并重新启用 CDC。 或者,在运行
ALTER COLUMN命令之前禁用 CDC,然后在ALTER COLUMN更改后重新启用 CDC。
错误 8169 - 从字符串转换为 uniqueidentifier 时转换失败
原因:当发出 ALTER COLUMN 命令以在表启用了 CDC 时更改列的数据类型时,会发生此错误。 例如,如果表具有 char(x)、 nvarchar(x)、 nvarchar(x) 列,并将数据类型更改为 uniqueidentifier (例如:
ALTER TABLE table_name ALTER COLUMN [column_name] uniqueidentifier),则可能在 sys.dm_cdc_errors 动态管理视图(DMV)中看到此错误。 错误 8169 指示更改表中不支持的数据转换,即使源表上的 ALTER 命令成功。建议:若要解决此问题,请在更改列后为表禁用并重新启用 CDC。 或者,在运行
ALTER COLUMN命令前禁用 CDC,然后在ALTER COLUMN更改后重新启用 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 用户是否属于 sysadmin 或 db_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';