【问题标题】:How to clean up all entries in a cdc table in MS SQL?如何在 MS SQL 中清理 cdc 表中的所有条目?
【发布时间】:2021-08-31 16:49:07
【问题描述】:

阅读 Microsoft Docs 这是相关的系统过程: sys.sp_cdc_cleanup_change_table

我试过这样使用它:

DECLARE @max_lsn binary(10);
SET @max_lsn = sys.fn_cdc_get_max_lsn();
Exec sys.sp_cdc_cleanup_change_table
@capture_instance = N'dbo_mytable',
@low_water_mark = @max_lsn;

查询已成功执行,但使用查询再次检查表:

DECLARE @from_lsn binary(10), @to_lsn binary(10);
SET @from_lsn = sys.fn_cdc_get_min_lsn('dbo_mytable');
SET @to_lsn   = sys.fn_cdc_get_max_lsn();
SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_mytable
  (@from_lsn, @to_lsn, N'all');

仍然返回一个非空表。我对SQL不太熟悉。我错过了什么?

【问题讨论】:

  • 你确定@capture_instance参数值正确吗?如果您传递一个不存在的捕获实例,该过程将完成而不会出错,但什么也不做。您可以通过select capture_instance from cdc.change_tables 查看现有的捕获实例名称
  • @allmhuran:我很确定。正如您在我的第二个查询中看到的那样,捕获实例名称是相同的,并且它返回一个表。我像你说的那样使用了捕获实例名称。
  • Roger,只是想仔细检查一下您实际执行的操作在存储的 proc 调用中没有错字(即,我怀疑您的真实表名是 mytable ,您已经明智地对其进行了编辑以发布到 SO)。碰巧我建立了一个小测试并看到了同样的事情......但只是有时,我知道为什么。接听来电

标签: sql-server change-data-capture


【解决方案1】:

我为此做了一个小测试,是的,我看到了同样的东西。我花了几分钟才弄清楚发生了什么。

“陷阱”是文档中的这个小条目:

如果 cdc.lsn_time_mapping 中的其他条目与新的低水位线标识的条目共享相同的提交时间,则选择与该组条目关联的最小 LSN 作为低水位线。

换句话说,如果sys.fn_cdc_get_max_lsn() 的结果映射到还具有其他start_lsn 值与之关联的cdc.lsn_time_mapping.tran_begin_time,那么清理过程实际上不会使用sys.fn_cdc_get_max_lsn() 的值作为新的低水位线。

换句话说,如果您要清理的更改表中当前的最大 lsn 与其他 LSN 具有相同的tran_begin_time,并且它不是这些 LSN 中最低的,那么您无法获得“完整”清理变化表。

在这些情况下进行彻底清理的最简单方法可能是对目标表进行微小更改以提高最大 lsn 并强制一个新条目,并“希望”新条目不与任何其他具有相同 tran 开始时间的 LSN。

为了更明确,这是我的小测试。一遍又一遍地运行它会导致在某些情况下预测清理会失败(并且失败),而在其他情况下预测会成功(并且成功)。

/*
one time setup:

create table t(i int primary key, c char);
create table u(i int primary key, d char);
go

exec sp_cdc_enable_db;
go

exec sys.sp_cdc_enable_table @source_schema = 'dbo', 
                             @source_name = 't',     
                             @supports_net_changes = 1,
                             @role_name = null;

exec sys.sp_cdc_enable_table @source_schema = 'dbo',   
                             @source_name = 'u',       
                             @supports_net_changes = 1,
                             @role_name = null;
*/
set nocount on;

delete from t;
delete from u;
go

insert t select 1, 'a';
insert u select 1, 'b';
waitfor delay '00:00:01';
go

declare @fail int;

select   @fail = count(*)
from     cdc.lsn_time_mapping 
where    tran_begin_time = (
   select   tran_begin_time 
   from     cdc.lsn_time_mapping 
   where    start_lsn = sys.fn_cdc_get_max_lsn()
);

print iif(@fail > 1, 'this wont do the cleanup you expect', 'this will do the cleanup');

DECLARE @max_lsn binary(10) = sys.fn_cdc_get_max_lsn();
Exec sys.sp_cdc_cleanup_change_table
   @capture_instance = N'dbo_t',
   @low_water_mark = @max_lsn;
go

if exists (select * from cdc.dbo_t_ct) print 'did not cleanup';
else print 'did the cleanup';

【讨论】:

  • 非常感谢!!!如果没有你,天知道我需要多长时间才能弄清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多