我有一个两节点 SQL Server 2019 可用性组,其数据库为多个表启用了CDC 。CDC 用于跟踪尚未捕获到数据仓库中的事务。
可用性组配置了多子网故障转移,并具有可读的辅助组。
应用程序使用sp_repltrans复制通过 CDC 捕获的事务,以获取事务列表,然后通过未记录的函数读取该列表fn_dump_dblog
。一旦捕获事务并将其集成到数据仓库中,应用程序就会通过sp_repldone将该事务标记为已复制。我们将其配置为ApplicationIntent=ReadOnly
自动连接到可用性组的可读辅助节点。
捕获/集成过程似乎运行良好,并且在可用性组故障转移期间恢复良好,根据需要自动切换到其他节点以维持与可读辅助节点的连接。事务被捕获到数据仓库中。
一旦事务被复制到数据仓库中,应用程序就会sp_repldone
在辅助数据库上执行,看起来成功了,但事务从未在主数据库上被标记为已复制,导致事务日志REPLICATION
在log_reuse_wait_desc
列中报告sys.databases
。
应用程序调用sp_repldone
如下:
EXEC sys.sp_repldone
@xactid = NULL
, @xact_seqno = NULL
, @numtrans= 0
, @time= 0
, @reset= 1;
以上是通过扩展事件捕获的sp_statement_completed
。扩展事件捕获会话还配置为捕获错误事件,并且不会报告任何事件。
如果我手动运行sp_repltrans
以获取未复制事务的列表,然后sp_repldone
在辅助数据库上针对该列表运行,它似乎成功而没有问题,但主数据库仍然认为事务尚未被复制。sp_repltrans
即在主服务器上运行仍然显示事务正在等待复制。
我在 sp_repldone 的文档中没有看到任何内容表明它可以或不能从可读的辅助设备运行;事实上,我猜测如果它无法将事务标记为已复制,它会返回错误,但也许在实现中存在错误。诚然,这种配置可能并不那么常见。如果我们将捕获/集成进程配置为附加到主节点,通过删除ApplicationIntent=ReadOnly
,然后sp_repldone
针对主节点执行确实可以正常运行,并且所有事务都被标记为已复制,从而允许事务日志重用。
是否需要更改某些内容才能使其针对可读的辅助工作?
我已通过 Azure 反馈网站报告了该行为(此处)。
作为背景,我假设这是一个自定义 CDC 解决方案,并且常规 CDC 作业不会运行来填充更改表并运行 sp_repldone,因此您必须运行 sp_repldone 才能在日志备份后重用日志文件空间。对于大多数情况,使用事务复制来填充目标数据库,或者使用内置的 CDC 解决方案并从主或辅助数据库副本读取更改数据会更简单。
sp_repldone “更新标识服务器最后一个分布式事务的记录。”,该记录存储在数据库中。所以它绝对不能在只读副本上工作,而且当你尝试时它可能会做什么,但它可能没有记录。
以及“辅助副本不能充当复制发布者或重新发布者,但必须配置复制,以便辅助副本可以在故障转移后接管”使用 Always On 可用性组配置复制
因此,内置事务复制也不支持这种情况。无法成功地将事务标记为从辅助副本复制可能是它不受支持的原因。
从辅助节点读取事务并连接到主节点以运行 sp_repldone可能工作正常,但您需要进行测试。