CDC清理作业未删除超期行的技术问询
CDC超期数据未被清理的原因分析
核心原因:待清理行的__$end_lsn为NULL
CDC清理作业sys.sp_MScdc_cleanup_job的清理逻辑是仅删除__$end_lsn不为NULL,且该LSN对应的时间早于保留期截止时间的行。你提供的CDC表数据中,目标行的__$end_lsn均为NULL,这类行属于CDC标记为“未完成处理”的变更记录,清理作业会直接跳过它们。
为什么__$end_lsn会是NULL?
__$end_lsn由CDC捕获作业填充,只有当捕获作业完整处理完对应事务的所有变更后,才会为该行写入__$end_lsn值。出现NULL的常见场景:
- 捕获作业未正常运行或处理滞后:你的捕获作业配置为
continuous=1(持续运行模式),但可能存在作业中断、报错,或因maxtrans/maxscans配置限制导致处理速度跟不上变更量,未完成对该事务的收尾标记。 - 对应事务未完成/异常:如果生成这些变更的事务长时间未提交,或事务提交后日志读取出现异常,捕获作业无法确认事务已完成,就不会填充
__$end_lsn。
验证与排查步骤
- 检查捕获作业状态:查看SQL Server代理中CDC捕获作业的运行历史,确认是否有报错、中断情况。
- 手动触发捕获作业:执行
sys.sp_MScdc_capture_job手动运行捕获作业,之后检查CDC表的__$end_lsn是否被填充。 - 确认事务状态:通过
sys.fn_cdc_map_lsn_to_commit_time(__$start_lsn)查看对应事务的提交时间,若返回NULL则说明事务未提交,需排查事务异常。 - 验证清理逻辑:当
__$end_lsn被填充后,可手动执行以下语句验证是否符合清理条件:
SELECT * FROM [你的CDC表名] WHERE __$end_lsn IS NOT NULL AND sys.fn_cdc_map_lsn_to_time(__$end_lsn) < DATEADD(minute, -4320, GETDATE())
若查询返回目标行,再次运行清理作业即可删除。
内容的提问来源于stack exchange,提问作者Imran Qadir Baksh - Baloch
相关产品推荐
相关产品推荐

